ipsservices/ipssosplugin/src/ipsplgsearch.cpp
changeset 0 8466d47a6819
child 1 12c456ceeff2
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: This file implements classes TMsgContainer, Search, Search, Search. 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "emailtrace.h"
       
    20 #include "ipsplgheaders.h"
       
    21 
       
    22 
       
    23 // To skip deleted folder
       
    24 _LIT( KIpsPlgDeleted, "Deleted" );
       
    25 
       
    26 // ======== CLASS TSEARCHPARAMS ======== 
       
    27 
       
    28 // ======== MEMBER FUNCTIONS ======== 
       
    29 
       
    30 // ---------------------------------------------------------------------------
       
    31 // CIpsPlgSearch::TSearchParams::operator==()
       
    32 // ---------------------------------------------------------------------------
       
    33 //
       
    34 TBool CIpsPlgSearch::TSearchParams::operator==( 
       
    35     const TSearchParams& aParams ) const
       
    36     {
       
    37     FUNC_LOG;
       
    38     // This variable indicates if the search is same as previous search or
       
    39     // not. If the search is new, previous data can be reused.
       
    40     TBool isNew = EFalse;
       
    41     
       
    42     // Search strings must have an exact match
       
    43     TInt newCnt = aParams.iSearchStrings->Count();
       
    44     TInt oldCnt = iSearchStrings ? iSearchStrings->Count() : KErrNotFound;
       
    45     if ( newCnt == oldCnt )
       
    46         {
       
    47         while ( !isNew && --newCnt >= 0 )
       
    48             {
       
    49             while ( !isNew && --oldCnt >= 0 )
       
    50                 {
       
    51                 // Even if one of the items fails, the search is different.
       
    52                 if ( ( *aParams.iSearchStrings )[newCnt].Compare( 
       
    53                     ( *iSearchStrings )[oldCnt] ) )
       
    54                     {
       
    55                     isNew = ETrue;
       
    56                     }
       
    57                 }
       
    58             }
       
    59         }
       
    60     else
       
    61         {
       
    62         // This search has different 
       
    63         isNew = ETrue;
       
    64         }
       
    65     
       
    66     // Search strings are the same than in previous round. If search
       
    67     // folders are added, but not removed, then search can continue
       
    68     // from last location.
       
    69     if ( !isNew )
       
    70         {
       
    71         isNew = EFalse;
       
    72         newCnt = aParams.iFolderIds.Count();
       
    73         oldCnt = iFolderIds.Count();
       
    74 
       
    75         // If folder count has been added, look for added folders.
       
    76         // If there is folder removed, search has to be started again.
       
    77         if ( newCnt >= oldCnt )
       
    78             {
       
    79             TInt hits = 0;
       
    80             TBool found = EFalse;
       
    81             
       
    82             // All of the old folders must be found from the new folders.
       
    83             for ( TInt old = 0; old < oldCnt; old++ )
       
    84                 {
       
    85                 found = EFalse;
       
    86                 
       
    87                 for ( TInt item = 0; !found && item < newCnt; item++ )
       
    88                     {
       
    89                     found = iFolderIds[old] == aParams.iFolderIds[item];
       
    90                     hits += found;
       
    91                     }
       
    92                 }    
       
    93             
       
    94             isNew = hits != oldCnt;                                        
       
    95             }                                
       
    96         }
       
    97     // Test is about: "is the new search the same as previous?" 
       
    98     // so if the result of the above analyze is "new search", in that 
       
    99     // case we must return the answer: "no, search is not the same".
       
   100     // Confusing huh?
       
   101     return !isNew;
       
   102     }
       
   103     
       
   104 // ======== CLASS TMSGCONTAINER ======== 
       
   105 
       
   106 // ---------------------------------------------------------------------------
       
   107 // CIpsPlgSearch::TMsgContainer::TMsgContainer()
       
   108 // ---------------------------------------------------------------------------
       
   109 //
       
   110 CIpsPlgSearch::TMsgContainer::TMsgContainer( 
       
   111     const TMsvId& aId, 
       
   112     const TFSMailSortCriteria& aCriteria,
       
   113     CMsvSession& aMsvSession )
       
   114     :
       
   115     iId( aId ),
       
   116     iCriteria( aCriteria ),
       
   117     iMsvSession( aMsvSession )
       
   118     {
       
   119     FUNC_LOG;
       
   120     }
       
   121 
       
   122 // ---------------------------------------------------------------------------
       
   123 // CIpsPlgSearch::TMsgContainer::TMsgContainer()
       
   124 // ---------------------------------------------------------------------------
       
   125 //
       
   126 TBool CIpsPlgSearch::TMsgContainer::operator>( 
       
   127     const TMsgContainer& aMsgContainer ) const
       
   128     {
       
   129     FUNC_LOG;
       
   130     TBool result = EFalse;
       
   131     
       
   132     switch ( iCriteria.iField )
       
   133         {
       
   134     default:        
       
   135     case EFSMailDontCare:
       
   136         break;
       
   137         
       
   138     case EFSMailSortByDate:
       
   139         result = Entry( iId ).iDate > Entry( aMsgContainer.Id() ).iDate;
       
   140         break;
       
   141 
       
   142     case EFSMailSortBySender:
       
   143         {
       
   144         HBufC* leftSender = NULL;
       
   145         HBufC* rightSender = NULL;
       
   146         
       
   147         GetSenderStringsCC( 
       
   148             iId, 
       
   149             aMsgContainer.Id(),  
       
   150             leftSender, 
       
   151             rightSender );
       
   152         
       
   153         result = *leftSender > *rightSender;
       
   154         CleanupStack::PopAndDestroy( 2, leftSender ); 
       
   155         }
       
   156         break;
       
   157     
       
   158     case EFSMailSortBySubject:
       
   159         {
       
   160         HBufC* leftSubject = NULL;
       
   161         HBufC* rightSubject = NULL;
       
   162         
       
   163         GetSubjectStringsCC( 
       
   164             iId, 
       
   165             aMsgContainer.Id(), 
       
   166             leftSubject, 
       
   167             rightSubject );
       
   168 
       
   169         result = *leftSubject > *rightSubject;
       
   170         CleanupStack::PopAndDestroy( 2, leftSubject ); 
       
   171         }
       
   172         break;
       
   173 
       
   174     case EFSMailSortByPriority:
       
   175         result = Entry( iId ).Priority() > Entry( aMsgContainer.Id() ).Priority();        
       
   176         break;
       
   177     
       
   178     case EFSMailSortByFlagStatus:
       
   179         result = Entry( iId ).New() > Entry( aMsgContainer.Id() ).New();
       
   180         break;
       
   181     
       
   182     case EFSMailSortByUnread:
       
   183         result = Entry( iId ).Unread() > Entry( aMsgContainer.Id() ).Unread();
       
   184         break;
       
   185     
       
   186     case EFSMailSortBySize:
       
   187         result = Entry( iId ).iSize > Entry( aMsgContainer.Id() ).iSize;
       
   188         break;
       
   189     
       
   190     case EFSMailSortByAttachment:
       
   191         result = Entry( iId ).iDate > Entry( aMsgContainer.Id() ).iDate;        
       
   192         break;
       
   193         }
       
   194            
       
   195     return result;        
       
   196     }
       
   197 
       
   198 // ---------------------------------------------------------------------------
       
   199 // CIpsPlgSearch::TMsgContainer::TMsgContainer()
       
   200 // ---------------------------------------------------------------------------
       
   201 //
       
   202 TBool CIpsPlgSearch::TMsgContainer::operator>=( 
       
   203     const TMsgContainer& aMsgContainer ) const
       
   204     {
       
   205     FUNC_LOG;
       
   206     TBool result = EFalse;
       
   207     
       
   208     switch ( iCriteria.iField )
       
   209         {
       
   210     default:        
       
   211     case EFSMailDontCare:
       
   212         break;
       
   213         
       
   214     case EFSMailSortByDate:
       
   215         result = Entry( iId ).iDate >= Entry( aMsgContainer.Id() ).iDate;
       
   216         break;
       
   217         
       
   218     case EFSMailSortBySender:
       
   219         {
       
   220         HBufC* leftSender = NULL;
       
   221         HBufC* rightSender = NULL;
       
   222         
       
   223         GetSenderStringsCC( 
       
   224             iId, 
       
   225             aMsgContainer.Id(),  
       
   226             leftSender, 
       
   227             rightSender );
       
   228         
       
   229         result = *leftSender >= *rightSender;
       
   230         CleanupStack::PopAndDestroy( 2, leftSender ); 
       
   231         }
       
   232         break;
       
   233         
       
   234     case EFSMailSortBySubject:
       
   235         {
       
   236         HBufC* leftSubject = NULL;
       
   237         HBufC* rightSubject = NULL;
       
   238         
       
   239         GetSubjectStringsCC( 
       
   240             iId, 
       
   241             aMsgContainer.Id(), 
       
   242             leftSubject, 
       
   243             rightSubject );
       
   244 
       
   245         result = *leftSubject >= *rightSubject;
       
   246         CleanupStack::PopAndDestroy( 2, leftSubject ); 
       
   247         }
       
   248         break;
       
   249             
       
   250     case EFSMailSortByPriority:
       
   251         result = Entry( iId ).Priority() >= Entry( aMsgContainer.Id() ).Priority();        
       
   252         break;
       
   253     
       
   254     case EFSMailSortByFlagStatus:
       
   255         result = Entry( iId ).New() >= Entry( aMsgContainer.Id() ).New();
       
   256         break;
       
   257     
       
   258     case EFSMailSortByUnread:
       
   259         result = Entry( iId ).Unread() >= Entry( aMsgContainer.Id() ).Unread();
       
   260         break;
       
   261     
       
   262     case EFSMailSortBySize:
       
   263         result = Entry( iId ).iSize >= Entry( aMsgContainer.Id() ).iSize;
       
   264         break;
       
   265     
       
   266     case EFSMailSortByAttachment:
       
   267         result = Entry( iId ).iDate >= Entry( aMsgContainer.Id() ).iDate;        
       
   268         break;
       
   269         }
       
   270         
       
   271     return result;        
       
   272     }
       
   273 
       
   274 // ---------------------------------------------------------------------------
       
   275 // CIpsPlgSearch::TMsgContainer::TMsgContainer()
       
   276 // ---------------------------------------------------------------------------
       
   277 //
       
   278 TBool CIpsPlgSearch::TMsgContainer::operator<=( 
       
   279     const TMsgContainer& aMsgContainer ) const
       
   280     {
       
   281     FUNC_LOG;
       
   282     TBool result = EFalse;
       
   283     
       
   284     switch ( iCriteria.iField )
       
   285         {
       
   286     default:        
       
   287     case EFSMailDontCare:
       
   288         break;
       
   289         
       
   290     case EFSMailSortByDate:
       
   291         result = Entry( iId ).iDate <= Entry( aMsgContainer.Id() ).iDate;
       
   292         break;
       
   293 
       
   294     case EFSMailSortBySender:
       
   295         {
       
   296         HBufC* leftSender = NULL;
       
   297         HBufC* rightSender = NULL;
       
   298         
       
   299         GetSenderStringsCC( 
       
   300             iId, 
       
   301             aMsgContainer.Id(),  
       
   302             leftSender, 
       
   303             rightSender );
       
   304         
       
   305         result = *leftSender <= *rightSender;
       
   306         CleanupStack::PopAndDestroy( 2, leftSender ); 
       
   307         }
       
   308         break;
       
   309     
       
   310     case EFSMailSortBySubject:
       
   311         {
       
   312         HBufC* leftSubject = NULL;
       
   313         HBufC* rightSubject = NULL;
       
   314         
       
   315         GetSubjectStringsCC( 
       
   316             iId, 
       
   317             aMsgContainer.Id(), 
       
   318             leftSubject, 
       
   319             rightSubject );
       
   320 
       
   321         result = *leftSubject <= *rightSubject;
       
   322         CleanupStack::PopAndDestroy( 2, leftSubject ); 
       
   323         }
       
   324         break;
       
   325 
       
   326     case EFSMailSortByPriority:
       
   327         result = Entry( iId ).Priority() <= Entry( aMsgContainer.Id() ).Priority();        
       
   328         break;
       
   329     
       
   330     case EFSMailSortByFlagStatus:
       
   331         result = Entry( iId ).New() <= Entry( aMsgContainer.Id() ).New();
       
   332         break;
       
   333     
       
   334     case EFSMailSortByUnread:
       
   335         result = Entry( iId ).Unread() <= Entry( aMsgContainer.Id() ).Unread();
       
   336         break;
       
   337     
       
   338     case EFSMailSortBySize:
       
   339         result = Entry( iId ).iSize <= Entry( aMsgContainer.Id() ).iSize;
       
   340         break;
       
   341     
       
   342     case EFSMailSortByAttachment:
       
   343         result = Entry( iId ).iDate <= Entry( aMsgContainer.Id() ).iDate;        
       
   344         break;
       
   345         }
       
   346         
       
   347     return result;        
       
   348     }
       
   349 
       
   350 // ---------------------------------------------------------------------------
       
   351 // CIpsPlgSearch::TMsgContainer::GetSenderStringsCC()
       
   352 // ---------------------------------------------------------------------------
       
   353 //
       
   354 void CIpsPlgSearch::TMsgContainer::GetSenderStringsCC( 
       
   355     const TMsvId aLeft, 
       
   356     const TMsvId aRight,
       
   357     HBufC*& aLeftSender,
       
   358     HBufC*& aRightSender ) const
       
   359     {
       
   360     FUNC_LOG;
       
   361     TMsvEntry entry = Entry( aLeft );
       
   362     aLeftSender = entry.iDetails.Alloc();
       
   363     TRAP_IGNORE( CleanupStack::PushL( aLeftSender ) );
       
   364     
       
   365     entry = Entry( aRight );
       
   366     aRightSender = entry.iDetails.Alloc();
       
   367     TRAP_IGNORE( CleanupStack::PushL( aRightSender ) );
       
   368     }
       
   369 
       
   370 // ---------------------------------------------------------------------------
       
   371 // CIpsPlgSearch::TMsgContainer::GetSubjectStringsCC()
       
   372 // ---------------------------------------------------------------------------
       
   373 //
       
   374 void CIpsPlgSearch::TMsgContainer::GetSubjectStringsCC( 
       
   375     const TMsvId aLeft, 
       
   376     const TMsvId aRight,
       
   377     HBufC*& aLeftSubject,
       
   378     HBufC*& aRightSubject ) const
       
   379     {
       
   380     FUNC_LOG;
       
   381     TMsvEntry entry = Entry( aLeft );
       
   382     aLeftSubject = entry.iDescription.Alloc();
       
   383     TRAP_IGNORE( CleanupStack::PushL( aLeftSubject ) );
       
   384     
       
   385     entry = Entry( aRight );
       
   386     aRightSubject = entry.iDescription.Alloc();
       
   387     TRAP_IGNORE( CleanupStack::PushL( aRightSubject ) );
       
   388     }
       
   389 
       
   390 // ---------------------------------------------------------------------------
       
   391 // CIpsPlgSearch::TMsgContainer::TMsgContainer()
       
   392 // ---------------------------------------------------------------------------
       
   393 //
       
   394 CIpsPlgSearch::TMsgContainer& CIpsPlgSearch::TMsgContainer::operator=( 
       
   395     const TMsgContainer& aMsgContainer )
       
   396     {
       
   397     FUNC_LOG;
       
   398     iId = aMsgContainer.Id();
       
   399     return *this;
       
   400     }
       
   401 
       
   402 // ---------------------------------------------------------------------------
       
   403 // CIpsPlgSearch::TMsgContainer::Entry()
       
   404 // ---------------------------------------------------------------------------
       
   405 //
       
   406 TMsvEntry CIpsPlgSearch::TMsgContainer::Entry( const TMsvId aId ) const
       
   407     {
       
   408     FUNC_LOG;
       
   409     return CIpsPlgSearch::TMsgContainer::Entry( iMsvSession, aId );
       
   410     }
       
   411     
       
   412 // ---------------------------------------------------------------------------
       
   413 // CIpsPlgSearch::TMsgContainer::Entry()
       
   414 // ---------------------------------------------------------------------------
       
   415 //
       
   416 TMsvEntry CIpsPlgSearch::TMsgContainer::Entry( 
       
   417     CMsvSession& aMsvSession, 
       
   418     const TMsvId aId )
       
   419     {
       
   420     FUNC_LOG;
       
   421     TMsvId service;
       
   422     TMsvEntry entry;
       
   423     aMsvSession.GetEntry( aId, service, entry );
       
   424     return entry;
       
   425     }
       
   426 
       
   427 // ======== CLASS CIPSPLGSEARCH ========     
       
   428     
       
   429 // ======== CONSTRUCTORS & DESTRUCTOR ========
       
   430 
       
   431 // ---------------------------------------------------------------------------
       
   432 // CIpsPlgSearch::NewL()
       
   433 // ---------------------------------------------------------------------------
       
   434 //
       
   435 CIpsPlgSearch* CIpsPlgSearch::NewL(
       
   436     CMsvSession& aMsvSession,
       
   437     CIpsPlgSosBasePlugin& aPlugin )
       
   438     {
       
   439     FUNC_LOG;
       
   440     CIpsPlgSearch* self = CIpsPlgSearch::NewLC( aMsvSession, aPlugin );
       
   441     CleanupStack::Pop( self );
       
   442     return self;
       
   443     }
       
   444 
       
   445 // ---------------------------------------------------------------------------
       
   446 // CIpsPlgSearch::NewLC()
       
   447 // ---------------------------------------------------------------------------
       
   448 //
       
   449 CIpsPlgSearch* CIpsPlgSearch::NewLC(
       
   450     CMsvSession& aMsvSession,
       
   451     CIpsPlgSosBasePlugin& aPlugin )
       
   452     {
       
   453     FUNC_LOG;
       
   454     CIpsPlgSearch* self = new( ELeave ) CIpsPlgSearch( aMsvSession, aPlugin );
       
   455     CleanupStack::PushL( self );
       
   456     self->ConstructL();
       
   457     return self;
       
   458     }
       
   459 
       
   460 // ---------------------------------------------------------------------------
       
   461 // CIpsPlgSearch::~CIpsPlgSearch()
       
   462 // ---------------------------------------------------------------------------
       
   463 //
       
   464 CIpsPlgSearch::~CIpsPlgSearch()
       
   465     {
       
   466     FUNC_LOG;
       
   467     // Any running search operations must be cancelled before deletion.
       
   468     if ( iOperation )
       
   469         {
       
   470         iOperation->Cancel();
       
   471         }
       
   472         
       
   473     delete iOperation;
       
   474     iOperation = NULL;
       
   475     
       
   476     iObserver = NULL;
       
   477     
       
   478     delete iActiveEntry;
       
   479     iActiveEntry = NULL;
       
   480     
       
   481     delete iMapper;
       
   482     iMapper = NULL;
       
   483     
       
   484     iCache.Reset();
       
   485     iEmailMessages.Reset();
       
   486     }
       
   487 
       
   488 // ---------------------------------------------------------------------------
       
   489 // CIpsPlgSearch::CIpsPlgSearch()
       
   490 // ---------------------------------------------------------------------------
       
   491 //
       
   492 CIpsPlgSearch::CIpsPlgSearch(
       
   493     CMsvSession& aMsvSession,
       
   494     CIpsPlgSosBasePlugin& aPlugin )
       
   495     :
       
   496     iMsvSession( aMsvSession ),
       
   497     iActiveEntry( NULL ),
       
   498     iOperation( NULL ),
       
   499     iObserver( NULL ),
       
   500     iPlugin( aPlugin ),
       
   501     iMapper( NULL )
       
   502     {
       
   503     FUNC_LOG;
       
   504     }
       
   505 
       
   506 // ---------------------------------------------------------------------------
       
   507 // CIpsPlgSearch::ConstructL()
       
   508 // ---------------------------------------------------------------------------
       
   509 //
       
   510 void CIpsPlgSearch::ConstructL()
       
   511     {
       
   512     FUNC_LOG;
       
   513     iMapper = CIpsPlgMsgMapper::NewL( iMsvSession, iPlugin );
       
   514     iActiveEntry = iMsvSession.GetEntryL( KMsvLocalServiceIndexEntryId );
       
   515     }
       
   516 
       
   517 // ---------------------------------------------------------------------------
       
   518 // CIpsPlgSearch::Cancel()
       
   519 // ---------------------------------------------------------------------------
       
   520 //
       
   521 void CIpsPlgSearch::Cancel()
       
   522     {
       
   523     FUNC_LOG;
       
   524     // Cancel the operation before deleting.
       
   525     if ( iOperation )
       
   526         {
       
   527         iOperation->Cancel();
       
   528         }
       
   529         
       
   530     // All checks are based on pointer value, so make it NULL
       
   531     delete iOperation;
       
   532     iOperation = NULL;
       
   533     
       
   534     }
       
   535 
       
   536 // ---------------------------------------------------------------------------
       
   537 // CIpsPlgSearch::ClearCache()
       
   538 // ---------------------------------------------------------------------------
       
   539 //
       
   540 void CIpsPlgSearch::ClearCache()
       
   541     {
       
   542     FUNC_LOG;
       
   543     iCache.Reset();
       
   544     }
       
   545 
       
   546 // ---------------------------------------------------------------------------
       
   547 // CIpsPlgSearch::GetFoldersL()
       
   548 // ---------------------------------------------------------------------------
       
   549 //
       
   550 void CIpsPlgSearch::GetFoldersL( TSearchParams& aParams )
       
   551     {
       
   552     FUNC_LOG;
       
   553     iActiveEntry->SetEntryL( aParams.iMailbox.Id() );
       
   554     
       
   555     if ( iActiveEntry->Entry().iMtm == KSenduiMtmPop3Uid )
       
   556         {
       
   557         aParams.iFolderIds.AppendL( 
       
   558             TFSMailMsgId( iPlugin.PluginId(), aParams.iMailbox.Id() ) );
       
   559         return;
       
   560         }
       
   561     const TInt folders = iActiveEntry->Count();
       
   562     for ( TInt folder = 0; folder < folders; folder++ )
       
   563         {
       
   564         const TMsvEntry& entry = ( *iActiveEntry )[folder];
       
   565         if ( entry.iType == KUidMsvFolderEntry &&
       
   566              entry.iDescription.Compare( KIpsPlgDeleted ) )
       
   567             {
       
   568             GetFoldersL( entry.Id(), aParams.iFolderIds );
       
   569             }
       
   570         }
       
   571     }
       
   572 
       
   573 // ---------------------------------------------------------------------------
       
   574 // CIpsPlgSearch::GetFoldersL()
       
   575 // ---------------------------------------------------------------------------
       
   576 void CIpsPlgSearch::GetFoldersL( 
       
   577     const TMsvId aFolderId, 
       
   578     RArray<TFSMailMsgId>& aFolders )
       
   579     {
       
   580     FUNC_LOG;
       
   581     // Add this folder to array.
       
   582     aFolders.AppendL( TFSMailMsgId( iPlugin.PluginId(), aFolderId ) );
       
   583     
       
   584     CMsvEntry* entry = iMsvSession.GetEntryL( aFolderId );
       
   585     CleanupStack::PushL( entry );
       
   586 
       
   587     const TInt count = entry->Count();
       
   588     for ( TInt loop = 0; loop < count; loop++ )
       
   589         {
       
   590         const TMsvEntry& tEntry = (*entry)[loop];
       
   591         if ( tEntry.iType == KUidMsvFolderEntry )
       
   592             {
       
   593             GetFoldersL( tEntry.Id(), aFolders );
       
   594             }        
       
   595         }
       
   596 
       
   597     CleanupStack::PopAndDestroy( entry );
       
   598     }
       
   599 
       
   600 // ---------------------------------------------------------------------------
       
   601 // CIpsPlgSearch::SearchL()
       
   602 // ---------------------------------------------------------------------------
       
   603 //
       
   604 void CIpsPlgSearch::SearchL( 
       
   605     const TFSMailMsgId& aMailBoxId,
       
   606     const RArray<TFSMailMsgId>& aFolderIds,
       
   607     const RPointerArray<TDesC>& aSearchStrings,
       
   608     const TFSMailSortCriteria& aSortCriteria,
       
   609     MFSMailBoxSearchObserver& aSearchObserver )
       
   610     {
       
   611     FUNC_LOG;
       
   612     if ( iOperation )
       
   613         {
       
   614         // if there is ongoing search, it must be canceled
       
   615         // according to UI specs
       
   616         Cancel();
       
   617         }
       
   618 
       
   619     // Create search parameters group for init.
       
   620     TSearchParams newSearch( 
       
   621         aSearchStrings, 
       
   622         aMailBoxId, 
       
   623         aFolderIds,  
       
   624         aSortCriteria );
       
   625 
       
   626     // If folder list is empty, whole mailbox needs to be searched.
       
   627     if ( !newSearch.iFolderIds.Count() )
       
   628         {
       
   629         GetFoldersL( newSearch );
       
   630         }
       
   631     
       
   632     // If search strings are same than last time, then sorting is same.
       
   633     // Clear previous cache and continue.
       
   634     if ( iPreviousSearch == newSearch )
       
   635         {
       
   636         // At this point, append new folders to list.
       
   637         iCurrentSearch += newSearch;
       
   638         iPreviousSearch += newSearch;
       
   639         }
       
   640     else
       
   641         {
       
   642         ClearCache();
       
   643         iCurrentSearch = newSearch;
       
   644         iPreviousSearch = newSearch;
       
   645         }
       
   646             
       
   647     iCurrentMessage.SetPluginId( aMailBoxId.PluginId() );
       
   648     iObserver = &aSearchObserver;
       
   649         
       
   650     iOperation = CIpsPlgSearchOp::NewL( *this );
       
   651     }
       
   652 
       
   653 // ---------------------------------------------------------------------------
       
   654 // From class MIpsPlgSearch.
       
   655 // CIpsPlgSearch::Session()
       
   656 // ---------------------------------------------------------------------------
       
   657 //
       
   658 CMsvSession& CIpsPlgSearch::Session()
       
   659     {
       
   660     FUNC_LOG;
       
   661     return iMsvSession;
       
   662     }
       
   663 
       
   664 // ---------------------------------------------------------------------------
       
   665 // From class MIpsPlgSearch.
       
   666 // CIpsPlgSearch::MailboxId()
       
   667 // ---------------------------------------------------------------------------
       
   668 //
       
   669 TMsvId CIpsPlgSearch::MailboxId()
       
   670     {
       
   671     FUNC_LOG;
       
   672     return iCurrentSearch.iMailbox.Id();
       
   673     }
       
   674 
       
   675 // ---------------------------------------------------------------------------
       
   676 // From class MIpsPlgSearch.
       
   677 // CIpsPlgSearch::FolderId()
       
   678 // ---------------------------------------------------------------------------
       
   679 //
       
   680 TMsvId CIpsPlgSearch::FolderId()
       
   681     {
       
   682     FUNC_LOG;
       
   683     return iActiveEntry->EntryId();
       
   684     }
       
   685 
       
   686 // ---------------------------------------------------------------------------
       
   687 // From class MIpsPlgSearch.
       
   688 // CIpsPlgSearch::CurrentMessage()
       
   689 // ---------------------------------------------------------------------------
       
   690 //
       
   691 const TFSMailMsgId& CIpsPlgSearch::CurrentMessage() const
       
   692     {
       
   693     FUNC_LOG;
       
   694     return iCurrentMessage;
       
   695     }
       
   696 
       
   697 // ---------------------------------------------------------------------------
       
   698 // From class MIpsPlgSearch.
       
   699 // CIpsPlgSearch::SearchStringsL()
       
   700 // ---------------------------------------------------------------------------
       
   701 //
       
   702 const CDesC16Array& CIpsPlgSearch::SearchStringsL()
       
   703     {
       
   704     FUNC_LOG;
       
   705     return *iCurrentSearch.iSearchStrings;
       
   706     }
       
   707 
       
   708 // ---------------------------------------------------------------------------
       
   709 // From class MIpsPlgSearch.
       
   710 // CIpsPlgSearch::MatchFound()
       
   711 // ---------------------------------------------------------------------------
       
   712 //
       
   713 void CIpsPlgSearch::MatchFoundL()
       
   714     {
       
   715     FUNC_LOG;
       
   716     // Set current email as an entry and create messages for both cache and
       
   717     // observer, for now like this.
       
   718     iActiveEntry->SetEntryL( iCurrentMessage.Id() );                
       
   719     iCache.AppendL( SendToObserverL() );
       
   720     }
       
   721     
       
   722 // ---------------------------------------------------------------------------
       
   723 // CIpsPlgSearch::SendToObserverL()
       
   724 // ---------------------------------------------------------------------------
       
   725 //
       
   726 TFSMailMsgId CIpsPlgSearch::SendToObserverL()
       
   727     {
       
   728     FUNC_LOG;
       
   729     CFSMailMessage* obsMail = iMapper->GetMailMessageL( *iActiveEntry );
       
   730     CleanupStack::PushL( obsMail );    
       
   731     
       
   732     iObserver->MatchFoundL( obsMail );    
       
   733     
       
   734     CleanupStack::Pop( obsMail );
       
   735     return obsMail->GetMessageId();        
       
   736     }
       
   737 
       
   738 // ---------------------------------------------------------------------------
       
   739 // From class MIpsPlgSearch.
       
   740 // CIpsPlgSearch::SearchFinished()
       
   741 // ---------------------------------------------------------------------------
       
   742 //
       
   743 void CIpsPlgSearch::SearchFinishedL()
       
   744     {
       
   745     FUNC_LOG;
       
   746     iObserver->SearchCompletedL();
       
   747     
       
   748     delete iOperation;
       
   749     iOperation = NULL;
       
   750     }
       
   751     
       
   752 // ---------------------------------------------------------------------------
       
   753 // CIpsPlgSearch::NextItem()
       
   754 // ---------------------------------------------------------------------------
       
   755 //
       
   756 CIpsPlgSearch::TMsgContainer& CIpsPlgSearch::NextItem()
       
   757     {
       
   758     FUNC_LOG;
       
   759     if ( iCurrentSearch.iSortCriteria.iOrder == EFSMailAscending )
       
   760         {
       
   761         return iEmailMessages[0];
       
   762         }
       
   763     else
       
   764         {
       
   765         return iEmailMessages[iEmailMessages.Count() - 1];
       
   766         }
       
   767     }
       
   768    
       
   769 // ---------------------------------------------------------------------------
       
   770 // From class MIpsPlgSearch.
       
   771 // CIpsPlgSearch::NextMessageL()
       
   772 // ---------------------------------------------------------------------------
       
   773 //
       
   774 CImEmailMessage* CIpsPlgSearch::NextMessageL()
       
   775     {
       
   776     FUNC_LOG;
       
   777     // Items, that are already in cache, are not needed to be searched.
       
   778     while ( iEmailMessages.Count() )
       
   779         {
       
   780         TFSMailMsgId id(
       
   781             iCurrentSearch.iMailbox.PluginId().iUid, NextItem().Id() );
       
   782             
       
   783         TInt index=KErrNotFound;
       
   784         TInt count = iCache.Count();
       
   785         
       
   786         for( TInt i=0; i<count; i++ )
       
   787             {
       
   788             if ( iCache[i].Id() == id.Id() )
       
   789                 {
       
   790                 index = i;
       
   791                 }
       
   792             }
       
   793         
       
   794         if ( index > KErrNotFound )
       
   795             {
       
   796             iActiveEntry->SetEntryL( id.Id() );
       
   797             
       
   798             if( iCurrentSearch.iSortCriteria.iOrder == EFSMailAscending )
       
   799             	{
       
   800                 iEmailMessages.Remove( 0 );
       
   801             	}
       
   802             else
       
   803             	{
       
   804             	iEmailMessages.Remove( iEmailMessages.Count()-1 );
       
   805             	}            
       
   806             SendToObserverL();
       
   807             }
       
   808         else
       
   809             {
       
   810             break;
       
   811             }
       
   812         }
       
   813 
       
   814     // Return next available message.        
       
   815     if ( iEmailMessages.Count() )
       
   816         {
       
   817         iCurrentMessage.SetId( NextItem().Id() );
       
   818         
       
   819         if( iCurrentSearch.iSortCriteria.iOrder == EFSMailAscending )
       
   820         	{
       
   821             iEmailMessages.Remove( 0 );
       
   822         	}
       
   823         else
       
   824         	{
       
   825         	iEmailMessages.Remove( iEmailMessages.Count()-1 );
       
   826         	}
       
   827         iActiveEntry->SetEntryL( iCurrentMessage.Id() );
       
   828         return CImEmailMessage::NewL( *iActiveEntry );
       
   829         }
       
   830     else
       
   831         {
       
   832         // Empty, return Null index, so the search can be finished.
       
   833         return NULL;
       
   834         }
       
   835     }    
       
   836     
       
   837 // ---------------------------------------------------------------------------
       
   838 // From class MIpsPlgSearch.
       
   839 // CIpsPlgSearch::MessageHeaderL()
       
   840 // ---------------------------------------------------------------------------
       
   841 //
       
   842 CImHeader* CIpsPlgSearch::MessageHeaderL()
       
   843     {
       
   844     FUNC_LOG;
       
   845     CImHeader* header = NULL;
       
   846     CMsvStore* store = iActiveEntry->EditStoreL();
       
   847     CleanupStack::PushL( store );    
       
   848     
       
   849     if ( store->IsPresentL( KUidMsgFileIMailHeader ) )
       
   850         {        
       
   851         header = CImHeader::NewLC();
       
   852         header->RestoreL( *store );
       
   853         CleanupStack::Pop( header );
       
   854         }
       
   855         
       
   856     CleanupStack::PopAndDestroy( store );        
       
   857     return header;
       
   858     }
       
   859 
       
   860 // ---------------------------------------------------------------------------
       
   861 // From class MIpsPlgSearch.
       
   862 // CIpsPlgSearch::GetSubjectL()
       
   863 // ---------------------------------------------------------------------------
       
   864 //
       
   865 void CIpsPlgSearch::GetSubjectL( RBuf& aSubject )
       
   866     {
       
   867     FUNC_LOG;
       
   868     TMsvEntry email = iActiveEntry->Entry();
       
   869     aSubject.CreateL( email.iDescription );
       
   870     }
       
   871 
       
   872 // ---------------------------------------------------------------------------
       
   873 // From class MIpsPlgSearch.
       
   874 // CIpsPlgSearch::GetSenderL()
       
   875 // ---------------------------------------------------------------------------
       
   876 //
       
   877 void CIpsPlgSearch::GetSenderL( RBuf& aSubject )
       
   878     {
       
   879     FUNC_LOG;
       
   880     TMsvEntry email = iActiveEntry->Entry();
       
   881     aSubject.CreateL( email.iDetails );
       
   882     }
       
   883 
       
   884 // ---------------------------------------------------------------------------
       
   885 // From class MIpsPlgSearch.
       
   886 // CIpsPlgSearch::Sort()
       
   887 // ---------------------------------------------------------------------------
       
   888 //
       
   889 void CIpsPlgSearch::Sort()
       
   890     {
       
   891     FUNC_LOG;
       
   892     // Here we use quick sort algorithm
       
   893     QuickSort( iEmailMessages, 0, iEmailMessages.Count() - 1 );
       
   894     }
       
   895 
       
   896 // ---------------------------------------------------------------------------
       
   897 // CIpsPlgSearch::QuickSort()
       
   898 // ---------------------------------------------------------------------------
       
   899 //
       
   900 void CIpsPlgSearch::QuickSort( 
       
   901     RArray<TMsgContainer>& aMessages, 
       
   902     TInt aLeft, 
       
   903     TInt aRight )
       
   904     {
       
   905     FUNC_LOG;
       
   906     if( aMessages.Count() <= 1 )
       
   907         {
       
   908         return;
       
   909         }
       
   910     TInt leftHold = aLeft;
       
   911     TInt rightHold = aRight;
       
   912     TMsgContainer pivot = aMessages[aLeft];
       
   913 
       
   914     while ( aLeft < aRight )
       
   915         {
       
   916         while ( ( aMessages[aRight] >= pivot ) && ( aLeft < aRight ) )
       
   917             {            
       
   918             aRight--;
       
   919             }
       
   920             
       
   921         if (aLeft != aRight)
       
   922             {
       
   923             aMessages[aLeft] = aMessages[aRight];
       
   924             aLeft++;
       
   925             }
       
   926 
       
   927         while ( ( aMessages[aLeft] <= pivot ) && ( aLeft < aRight ) )
       
   928             {            
       
   929             aLeft++;
       
   930             }
       
   931 
       
   932         if ( aLeft != aRight )
       
   933             {
       
   934             aMessages[aRight] = aMessages[aLeft];
       
   935             aRight--;
       
   936             }
       
   937         }
       
   938 
       
   939     aMessages[aLeft] = pivot;
       
   940     
       
   941     TInt pivotIndex = aLeft;
       
   942     aLeft = leftHold;
       
   943     aRight = rightHold;
       
   944     if ( aLeft < pivotIndex )
       
   945         {        
       
   946         QuickSort( aMessages, aLeft, pivotIndex-1);
       
   947         }
       
   948     
       
   949     if ( aRight > pivotIndex )
       
   950         {        
       
   951         QuickSort( aMessages, pivotIndex+1, aRight);
       
   952         }
       
   953     }
       
   954 
       
   955 // ---------------------------------------------------------------------------
       
   956 // From class MIpsPlgSearch.
       
   957 // CIpsPlgSearch::CollectMessagesL()
       
   958 // ---------------------------------------------------------------------------
       
   959 //
       
   960 void CIpsPlgSearch::CollectMessagesL()
       
   961     {
       
   962     FUNC_LOG;
       
   963     // Lets make a huge list of message id's. 
       
   964     iEmailMessages.Reset();    
       
   965     
       
   966     const TInt folders = iCurrentSearch.iFolderIds.Count();
       
   967     for ( TInt folder = 0; folder < folders; folder++ )
       
   968         {
       
   969         iActiveEntry->SetEntryL( iCurrentSearch.iFolderIds[folder].Id() );        
       
   970         const TInt msgs = iActiveEntry->Count();
       
   971         for ( TInt msg = 0; msg < msgs; msg++ )
       
   972             {
       
   973             const TMsvEntry& entry = ( *iActiveEntry )[msg];
       
   974             if ( entry.iType == KUidMsvMessageEntry &&
       
   975                  ( entry.iMtm.iUid == KSenduiMtmSmtpUidValue ||
       
   976                    entry.iMtm.iUid == iPlugin.MtmId().iUid ) )
       
   977                 {
       
   978                 iEmailMessages.AppendL( TMsgContainer( 
       
   979                     entry.Id(), iCurrentSearch.iSortCriteria, iMsvSession ) );
       
   980                 }        
       
   981             }
       
   982         }    
       
   983     }
       
   984     
       
   985 // End of File
       
   986