emailservices/emailstore/message_store/server/src/MsgStoreInMemorySortRowSet.cpp
changeset 0 8466d47a6819
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2006 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:  Message store in memory sort row set implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "MsgStoreInMemorySortRowSet.h"
       
    20 
       
    21 // ======================
       
    22 // CLASS: CIntegerRow
       
    23 // ======================
       
    24 
       
    25 // ==========================================================================
       
    26 // FUNCTION: Construct
       
    27 // ==========================================================================
       
    28 CIntegerRow::CIntegerRow( TMsgStoreId aMessageId, TInt64 aDate, TInt32 aValue ) 
       
    29 : iMessageId( aMessageId ), iDate( aDate ), iValue( aValue )
       
    30     {
       
    31     }
       
    32 
       
    33 // ==========================================================================
       
    34 // FUNCTION: ~CIntegerRow()
       
    35 // ==========================================================================
       
    36 CIntegerRow::~CIntegerRow()
       
    37     {
       
    38     }
       
    39     
       
    40 // ==========================================================================
       
    41 // FUNCTION: DateAsc
       
    42 // ==========================================================================
       
    43 TInt CIntegerRow::DateAsc(const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
    44 	{
       
    45     TInt rc = ( aFirst.iDate > aSecond.iDate ? 1 : ( aFirst.iDate == aSecond.iDate ? 0 : -1 ) );
       
    46     return rc;
       
    47     }
       
    48 
       
    49 // ==========================================================================
       
    50 // FUNCTION: DateDesc
       
    51 // ==========================================================================
       
    52 TInt CIntegerRow::DateDesc(const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
    53     {
       
    54     TInt rc = ( aSecond.iDate > aFirst.iDate ? 1 : ( aSecond.iDate == aFirst.iDate ? 0 : -1 ) );
       
    55     return rc;
       
    56     }
       
    57 
       
    58 // ==========================================================================
       
    59 // FUNCTION: ValueAscDateAsc
       
    60 // ==========================================================================
       
    61 TInt CIntegerRow::ValueAscDateAsc(const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
    62     {
       
    63     TInt rc = ( aFirst.iValue > aSecond.iValue ? 1 : ( aFirst.iValue == aSecond.iValue ? 0 : - 1) );
       
    64     if ( rc == 0 )
       
    65         {
       
    66         rc = ( aFirst.iDate > aSecond.iDate ? 1 : ( aFirst.iDate == aSecond.iDate ? 0 : - 1) );
       
    67         }
       
    68     return rc;
       
    69     }
       
    70 
       
    71 // ==========================================================================
       
    72 // FUNCTION: ValueAscDateDesc
       
    73 // ==========================================================================
       
    74 TInt CIntegerRow::ValueAscDateDesc(const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
    75     {
       
    76     TInt rc = ( aFirst.iValue > aSecond.iValue ? 1 : ( aFirst.iValue == aSecond.iValue ? 0 : - 1) );
       
    77     if ( rc == 0 )
       
    78         {
       
    79         rc = ( aSecond.iDate > aFirst.iDate ? 1 : ( aSecond.iDate == aFirst.iDate ? 0 : -1 ) );
       
    80         }
       
    81     return rc;
       
    82     }
       
    83 
       
    84 // ==========================================================================
       
    85 // FUNCTION: ValueDescDateAsc
       
    86 // ==========================================================================
       
    87 TInt CIntegerRow::ValueDescDateAsc(const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
    88     {
       
    89     TInt rc = ( aSecond.iValue > aFirst.iValue ? 1 : ( aSecond.iValue == aFirst.iValue ? 0 : - 1) );
       
    90     if ( rc == 0 )
       
    91         {
       
    92         rc = ( aFirst.iDate > aSecond.iDate ? 1 : ( aFirst.iDate == aSecond.iDate ? 0 : - 1) );
       
    93         }
       
    94     return rc;
       
    95     }
       
    96     
       
    97 // ==========================================================================
       
    98 // FUNCTION: ValueDescDateDesc
       
    99 // ==========================================================================
       
   100 TInt CIntegerRow::ValueDescDateDesc(const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
   101     {
       
   102     TInt rc = ( aSecond.iValue > aFirst.iValue ? 1 : ( aSecond.iValue == aFirst.iValue ? 0 : - 1) );
       
   103     if ( rc == 0 )
       
   104         {
       
   105         rc = ( aSecond.iDate > aFirst.iDate ? 1 : ( aSecond.iDate == aFirst.iDate ? 0 : -1 ) );
       
   106         }
       
   107     return rc;
       
   108     }
       
   109     
       
   110 // ==========================================================================
       
   111 // FUNCTION: IdAsc
       
   112 // ==========================================================================
       
   113 TInt CIntegerRow::MessageIdAsc( const CIntegerRow& aFirst, const CIntegerRow& aSecond )
       
   114     {
       
   115     return aFirst.iMessageId < aSecond.iMessageId ? -1 : ( aFirst.iMessageId == aSecond.iMessageId ) ? 0 : 1;
       
   116     }
       
   117 
       
   118 CIntegerSortGroup::CIntegerSortGroup( TInt64 aValue )
       
   119   : iValue(aValue), iCount(1)
       
   120     {
       
   121     }
       
   122 
       
   123 CIntegerSortGroup::~CIntegerSortGroup()
       
   124     {
       
   125     }
       
   126 
       
   127 TInt CIntegerSortGroup::ValueAscAndUpdateCount( const CIntegerSortGroup& aFirst, const CIntegerSortGroup& aSecond )
       
   128     {
       
   129     TInt rc = ( aFirst.iValue > aSecond.iValue ? 1 : ( aFirst.iValue == aSecond.iValue ? 0 : - 1) );
       
   130     if ( rc == 0 )
       
   131         {
       
   132         ++aSecond.iCount;
       
   133         }
       
   134     return rc;
       
   135     }
       
   136 
       
   137 TInt CIntegerSortGroup::ValueDescAndUpdateCount( const CIntegerSortGroup& aFirst, const CIntegerSortGroup& aSecond )
       
   138     {
       
   139     TInt rc = ( aSecond.iValue > aFirst.iValue ? 1 : ( aSecond.iValue == aFirst.iValue ? 0 : - 1) );
       
   140     if ( rc == 0 )
       
   141         {
       
   142         ++aSecond.iCount;
       
   143         }
       
   144     return rc;
       
   145     }
       
   146     
       
   147 TInt CIntegerSortGroup::ValueAsc( const CIntegerSortGroup& aFirst, const CIntegerSortGroup& aSecond )
       
   148     {
       
   149     TInt rc = ( aFirst.iValue > aSecond.iValue ? 1 : ( aFirst.iValue == aSecond.iValue ? 0 : - 1) );
       
   150     return rc;
       
   151     }
       
   152 
       
   153 TInt CIntegerSortGroup::ValueDesc( const CIntegerSortGroup& aFirst, const CIntegerSortGroup& aSecond )
       
   154     {
       
   155     TInt rc = ( aSecond.iValue > aFirst.iValue ? 1 : ( aSecond.iValue == aFirst.iValue ? 0 : - 1) );
       
   156     return rc;
       
   157     }
       
   158 
       
   159 // ==================================
       
   160 // CLASS: CMsgStoreSortResultRowSet
       
   161 // ==================================
       
   162 // ==========================================================================
       
   163 // FUNCTION: NewL
       
   164 // ==========================================================================
       
   165 CMsgStoreInMemorySortRowSet* CMsgStoreInMemorySortRowSet::NewL( const TMsgStoreSortCriteria& aSortCriteria, CContainerStoreSortingTable& aSortingTable )
       
   166     {
       
   167     CMsgStoreInMemorySortRowSet* self = new(ELeave) CMsgStoreInMemorySortRowSet( aSortCriteria, aSortingTable );
       
   168     CleanupStack::PushL( self );
       
   169     self->ConstructL();
       
   170     CleanupStack::Pop( self );
       
   171     return self;
       
   172     }
       
   173 
       
   174 // ==========================================================================
       
   175 // FUNCTION: CMsgStoreInMemorySortRowSet
       
   176 // ==========================================================================
       
   177 CMsgStoreInMemorySortRowSet::CMsgStoreInMemorySortRowSet( const TMsgStoreSortCriteria& aSortCriteria, CContainerStoreSortingTable& aSortingTable )
       
   178 : CMsgStoreSortResultRowSet( aSortCriteria, 0, 0, 0, 0, 0, 0, 0 ), 
       
   179   iSortCriteria( aSortCriteria ),
       
   180   iSortingTable( aSortingTable )
       
   181     {
       
   182     __LOG_CONSTRUCT( "msg", "CMsgStoreInMemorySortRowSet" )
       
   183     __LOG_CLOSE_BETWEEN_WRITES
       
   184     }
       
   185 
       
   186 // ==========================================================================
       
   187 // FUNCTION: ConstructL
       
   188 // ==========================================================================
       
   189 void CMsgStoreInMemorySortRowSet::ConstructL()
       
   190     {
       
   191     __LOG_ENTER("ConstructL")
       
   192 
       
   193     InitState();
       
   194     
       
   195     if ( iSortCriteria.iSortBy == EMsgStoreSortByReceivedDate )
       
   196     	{
       
   197 	    if ( iSortCriteria.iSortOrder == EMsgStoreSortDescending )
       
   198 	    	{
       
   199             iSortMethod = &CIntegerRow::DateDesc;
       
   200 	    	}
       
   201 	    else
       
   202 	    	{
       
   203             iSortMethod = &CIntegerRow::DateAsc;
       
   204 	    	}   
       
   205 	    
       
   206 	    //initial the UTC offset
       
   207 	    TLocale locale;
       
   208 	    iUtcOffsetInSeconds = locale.UniversalTimeOffset();   
       
   209     	}
       
   210     else
       
   211     	{
       
   212 	    if ( iSortCriteria.iSortOrder == EMsgStoreSortDescending )
       
   213 	        {
       
   214 	        if ( iSortCriteria.iSecondarySortOrder == EMsgStoreSortDescending )
       
   215 	            {
       
   216 	            iSortMethod = &CIntegerRow::ValueDescDateDesc;
       
   217 	            }
       
   218 	        else
       
   219 	            {
       
   220 	            iSortMethod = &CIntegerRow::ValueDescDateAsc;
       
   221 	            }
       
   222 	        }
       
   223 	    else
       
   224 	        {
       
   225 	        if ( iSortCriteria.iSecondarySortOrder == EMsgStoreSortDescending )
       
   226 	            {
       
   227 	            iSortMethod = &CIntegerRow::ValueAscDateDesc;
       
   228 	            }
       
   229 	        else
       
   230 	            {
       
   231 	            iSortMethod = &CIntegerRow::ValueAscDateAsc;
       
   232 	            }
       
   233 	        }
       
   234     	}
       
   235     
       
   236     __LOG_EXIT
       
   237     }
       
   238 
       
   239 // ==========================================================================
       
   240 // FUNCTION: Destructor
       
   241 // ==========================================================================
       
   242 CMsgStoreInMemorySortRowSet::~CMsgStoreInMemorySortRowSet()
       
   243     {
       
   244     iSortedIdArray.ResetAndDestroy();
       
   245     iSortedResultArray.Reset();
       
   246     iDbView.Close();
       
   247     iGroupNameArray.ResetAndDestroy();
       
   248     
       
   249     __LOG_DESTRUCT
       
   250     }
       
   251 		
       
   252 // ==========================================================================
       
   253 // FUNCTION: ToTopL
       
   254 // ==========================================================================
       
   255 void CMsgStoreInMemorySortRowSet::ToTopL()
       
   256     {
       
   257     __LOG_ENTER("ToTopL")
       
   258     
       
   259     //position the cursor to BEFORE the first element
       
   260     iCursorInWindow = -1;
       
   261     
       
   262     __LOG_EXIT
       
   263     }
       
   264 
       
   265 // ==========================================================================
       
   266 // FUNCTION: ToEndL
       
   267 // ==========================================================================
       
   268 void CMsgStoreInMemorySortRowSet::ToEndL()
       
   269     {
       
   270     __LOG_ENTER("ToEndL")
       
   271     //position the cursor to AFTER the last element
       
   272     iCursorInWindow = iSortedResultArray.Count();
       
   273     
       
   274     __LOG_EXIT
       
   275     }
       
   276 		
       
   277 // ==========================================================================
       
   278 // FUNCTION: HasMorePreviousL
       
   279 // ==========================================================================
       
   280 TBool CMsgStoreInMemorySortRowSet::HasMorePreviousL()
       
   281     {
       
   282     return iCursorInWindow > 0;
       
   283     }
       
   284 
       
   285 // ==========================================================================
       
   286 // FUNCTION: HasMoreNextL
       
   287 // ==========================================================================
       
   288 TBool CMsgStoreInMemorySortRowSet::HasMoreNextL()
       
   289     {
       
   290     return iCursorInWindow < iSortedResultArray.Count() - 1;
       
   291     }
       
   292 		
       
   293 // ==========================================================================
       
   294 // FUNCTION: NextL
       
   295 // ==========================================================================
       
   296 TMsgStoreId CMsgStoreInMemorySortRowSet::NextL()
       
   297     {
       
   298     TMsgStoreId id = KContainerInvalidId;
       
   299     ++iCursorInWindow;
       
   300     if ( iCursorInWindow < iSortedResultArray.Count() && iCursorInWindow >= 0 )
       
   301         {
       
   302         id = iSortedResultArray[ iCursorInWindow ]->MessageId();
       
   303         }
       
   304     else
       
   305         {
       
   306         //leave the iCursorInWindow at the end
       
   307         User::Leave( KErrOverflow );
       
   308         }
       
   309     return id;
       
   310     }
       
   311         
       
   312 // ==========================================================================
       
   313 // FUNCTION: PreviousL
       
   314 // ==========================================================================
       
   315 TMsgStoreId CMsgStoreInMemorySortRowSet::PreviousL()
       
   316     {
       
   317     TMsgStoreId id = KContainerInvalidId;
       
   318     --iCursorInWindow;
       
   319     if ( iCursorInWindow < iSortedResultArray.Count() && iCursorInWindow >= 0 )
       
   320         {
       
   321         id = iSortedResultArray[ iCursorInWindow ]->MessageId();
       
   322         }
       
   323     else
       
   324         {
       
   325         //leave the iCursorInWindow at the end
       
   326         User::Leave( KErrUnderflow );
       
   327         }
       
   328     return id;
       
   329     }
       
   330 		
       
   331 // ==========================================================================
       
   332 // FUNCTION: GotoL
       
   333 // ==========================================================================
       
   334 void CMsgStoreInMemorySortRowSet::GotoL( TContainerId aMessageId )
       
   335     {
       
   336     __LOG_ENTER_SUPPRESS("GotoL")
       
   337     __LOG_WRITE_FORMAT1_DEBUG3( "msgId=%x", aMessageId )
       
   338     CIntegerRow* tmpRow = new(ELeave) CIntegerRow( aMessageId, 0, 0 );
       
   339     CleanupStack::PushL( tmpRow );
       
   340     
       
   341     TInt rc = iSortedIdArray.FindInOrder( tmpRow, &CIntegerRow::MessageIdAsc );
       
   342     if ( rc < 0 )
       
   343         {
       
   344         User::Leave( KErrNotFound );
       
   345         }
       
   346     if ( rc < iSortedIdArray.Count() )
       
   347         {
       
   348     iCursorInWindow = iSortedResultArray.FindInOrder( iSortedIdArray[rc], iSortMethod );
       
   349         }
       
   350     else
       
   351         {
       
   352         User::Leave( KErrCorrupt );
       
   353         }
       
   354     CleanupStack::PopAndDestroy( tmpRow );
       
   355     }
       
   356 		
       
   357 
       
   358 // ==========================================================================
       
   359 // FUNCTION: SkipCurrentGroupL - for UI "group" support
       
   360 // ==========================================================================
       
   361 TBool CMsgStoreInMemorySortRowSet::SkipCurrentGroupL( TMsgStoreIteratorDirection aDirection, TUint& /*aItemsInGroup*/ )
       
   362     {
       
   363     __LOG_ENTER_SUPPRESS("SkipCurrentGroupL")
       
   364     
       
   365     if ( aDirection == EMsgStoreIteratorForward )
       
   366         {
       
   367         if ( !HasMorePreviousL() )
       
   368             {
       
   369             //at top of the cursor, return right away because there is NO "current group"
       
   370             //so the next (first) in result set will be the "next group"
       
   371             return ETrue;
       
   372             }
       
   373         }
       
   374     else
       
   375         {
       
   376         if ( !HasMoreNextL() )
       
   377             {
       
   378             //at bottom of the cursor, return right away because there is NO "current group" 
       
   379             //so the previous (last) in result set will be the "next group"
       
   380             return ETrue;
       
   381             }
       
   382         }
       
   383     
       
   384     CIntegerRow* curRow = iSortedResultArray[iCursorInWindow];
       
   385     __LOG_WRITE_FORMAT2_DEBUG3("Current msg: id=%X val=%ld", curRow->MessageId(), &curRow->StringVal() )
       
   386     TBool found = EFalse;
       
   387     
       
   388     TInt64 dateRangeStart = 0;
       
   389     TInt64 dateRangeEnd = 0;
       
   390     if ( iSortCriteria.iSortBy == EMsgStoreSortByReceivedDate )
       
   391     	{
       
   392     	GetDateRangeL( *curRow, aDirection, dateRangeStart, dateRangeEnd );
       
   393     	}
       
   394     
       
   395     while ( !found )
       
   396         {
       
   397         if ( aDirection == EMsgStoreIteratorForward )
       
   398             {
       
   399             iCursorInWindow++;
       
   400             }
       
   401         else
       
   402             {
       
   403             iCursorInWindow--;
       
   404             }
       
   405         
       
   406         if ( iCursorInWindow >= 0 && iCursorInWindow < iSortedResultArray.Count() )
       
   407             {
       
   408             CIntegerRow* nextRow = iSortedResultArray[iCursorInWindow];
       
   409             if ( iSortCriteria.iSortBy == EMsgStoreSortByReceivedDate )
       
   410             	{
       
   411             	TInt64 time = nextRow->ReceivedTime();
       
   412             	if ( time >= dateRangeEnd || time < dateRangeStart )
       
   413             		{
       
   414 	                found = ETrue;
       
   415 	                __LOG_WRITE_FORMAT2_DEBUG3("Next Group Found: id=%X time=%ld", nextRow->MessageId(), nextRow->ReceivedTime() )
       
   416             		}
       
   417             	}
       
   418             else
       
   419             	{
       
   420 	            if ( nextRow->Value() != curRow->Value() )
       
   421 	                {
       
   422 	                found = ETrue;
       
   423 	                __LOG_WRITE_FORMAT2_DEBUG3("Next Group Found: id=%X val=%d", nextRow->MessageId(), nextRow->Value() )
       
   424 	                }
       
   425             	}
       
   426             }
       
   427         else
       
   428         	{
       
   429         	break;  //Not found
       
   430         	}
       
   431         }
       
   432     
       
   433     if ( found )
       
   434         {
       
   435         if ( aDirection == EMsgStoreIteratorForward )
       
   436             {
       
   437             iCursorInWindow--;
       
   438             }
       
   439         else
       
   440             {
       
   441             iCursorInWindow++;
       
   442             }
       
   443         }
       
   444     return found;
       
   445     }
       
   446 
       
   447 
       
   448 // ==========================================================================
       
   449 // FUNCTION: GroupCountL
       
   450 // ==========================================================================
       
   451 TInt CMsgStoreInMemorySortRowSet::GroupCountL( RArray<TUint>& aItemsInGroup )
       
   452     {
       
   453     for ( TInt i = 0 ; i < iGroupNameArray.Count() ; i++ )
       
   454         {
       
   455         aItemsInGroup.Append( iGroupNameArray[i]->Count() );
       
   456         }
       
   457     
       
   458     return iGroupNameArray.Count();
       
   459     }
       
   460 
       
   461 // ==========================================================================
       
   462 // FUNCTION: SortedIdsL
       
   463 // ==========================================================================
       
   464 void CMsgStoreInMemorySortRowSet::SortedIdsL( RArray<TContainerId>& aIdArray )
       
   465 	{
       
   466 	aIdArray.Reset();
       
   467 	TContainerId msgId = 0;
       
   468 	
       
   469 	ToTopL();
       
   470 	
       
   471 	TInt err = KErrNone;
       
   472 	TBool hasMore = ETrue;
       
   473 	
       
   474 	while ( hasMore )
       
   475 		{
       
   476         TRAP( err, msgId = NextL() );
       
   477 		if ( err == KErrNone )
       
   478 			{
       
   479 			aIdArray.Append( msgId );
       
   480 			}
       
   481 		else if ( err == KErrOverflow )
       
   482 			{
       
   483 			hasMore = EFalse;
       
   484 			}
       
   485 		else
       
   486 			{
       
   487 			User::Leave( err );
       
   488 			}
       
   489 		}
       
   490 	}
       
   491 
       
   492 // ==========================================================================
       
   493 // FUNCTION: IndexOfL
       
   494 // ==========================================================================
       
   495 TInt CMsgStoreInMemorySortRowSet::IndexOfL( TContainerId aMessageId )
       
   496     {
       
   497     GotoL( aMessageId );
       
   498     return iCursorInWindow;
       
   499     }
       
   500 
       
   501 // ==========================================================================
       
   502 // FUNCTION: UpdateGroupList
       
   503 // ==========================================================================
       
   504 void CMsgStoreInMemorySortRowSet::UpdateGroupListL( TInt64 aValue )
       
   505     {
       
   506     CIntegerSortGroup *gn = NULL;
       
   507     
       
   508     if ( iSortCriteria.iSortBy == EMsgStoreSortByReceivedDate )
       
   509     	{
       
   510     	TTime startOfDay;
       
   511     	GetStartOfLocalDayL( aValue, startOfDay );
       
   512     	gn = new(ELeave) CIntegerSortGroup( startOfDay.Int64() );
       
   513     	}
       
   514     else
       
   515     	{
       
   516     	gn = new(ELeave) CIntegerSortGroup( aValue );
       
   517     	}
       
   518     
       
   519     CleanupStack::PushL( gn );
       
   520     TInt rc = KErrNone;
       
   521     if ( iSortCriteria.iSortOrder == EMsgStoreSortDescending )
       
   522         {
       
   523         rc = iGroupNameArray.InsertInOrder( gn, CIntegerSortGroup::ValueDescAndUpdateCount );
       
   524         }
       
   525     else
       
   526         {
       
   527         rc = iGroupNameArray.InsertInOrder( gn, CIntegerSortGroup::ValueAscAndUpdateCount );
       
   528         }
       
   529     
       
   530     if ( rc != KErrNone )
       
   531         {
       
   532         //can't insert due to duplicate or some other error, delete the object
       
   533         CleanupStack::PopAndDestroy( gn );
       
   534         }
       
   535     else
       
   536         {
       
   537         CleanupStack::Pop( gn );
       
   538         }
       
   539     }
       
   540 
       
   541 // ==========================================================================
       
   542 // FUNCTION: AppendL
       
   543 // ==========================================================================
       
   544 void CMsgStoreInMemorySortRowSet::AppendL( CIntegerRow* aRow )
       
   545     {
       
   546     __LOG_ENTER_SUPPRESS("AppendL")
       
   547     __LOG_WRITE_FORMAT2_DEBUG3( "msgId=%x time=%ld", aRow->MessageId(), aRow->ReceivedTime() )
       
   548     __LOG_WRITE_FORMAT1_DEBUG3( "value=%d", aRow->Value() )
       
   549     
       
   550     InsertInOrderL( aRow );
       
   551     TInt64 groupValue = GetGroupValue( *aRow );
       
   552     UpdateGroupListL( groupValue );    
       
   553     }
       
   554 
       
   555 // ==========================================================================
       
   556 // FUNCTION: SortL
       
   557 // ==========================================================================
       
   558 void CMsgStoreInMemorySortRowSet::SortL()
       
   559     {
       
   560     //This method is called by the ContainerStoreSortingTable perform "sort" action AFTER
       
   561     // appending all the rows by calling AppendL() for each row.  However, in this class,
       
   562     // "sorting" is performed IN the AppendL() method.  So rows are inserted into their 
       
   563     // sorted position as they are added to the list.
       
   564     }
       
   565 
       
   566 // ==========================================================================
       
   567 // FUNCTION: MessageUpdate
       
   568 // ==========================================================================
       
   569 void CMsgStoreInMemorySortRowSet::MessageUpdate ( TContainerId       aMessageId, 
       
   570                                                   TContainerId       aFolderId, 
       
   571                                                   TMsgStoreOperation aOperation, 
       
   572                                                   TUint              aFieldsChanged, 
       
   573                                                   const TDesC&       aFrom, 
       
   574                                                   const TDesC&       aTo, 
       
   575                                                   const TDesC&       aSubject,
       
   576                                                   TInt64             aDate )
       
   577     {
       
   578     __LOG_ENTER("MessageUpdate")
       
   579     
       
   580     TRAP_IGNORE( DoMessageUpdateL( aMessageId, aFolderId, aOperation, aFieldsChanged, aFrom, aTo, aSubject, aDate ) );
       
   581     
       
   582     __LOG_EXIT
       
   583     }
       
   584 
       
   585 // ==========================================================================
       
   586 // FUNCTION: DoMessageUpdateL
       
   587 // ==========================================================================
       
   588 void CMsgStoreInMemorySortRowSet::DoMessageUpdateL ( TContainerId       aMessageId, 
       
   589                                                   TContainerId       aFolderId, 
       
   590                                                   TMsgStoreOperation aOperation, 
       
   591                                                   TUint              /*aFieldsChanged*/, 
       
   592                                                   const TDesC&       /*aFrom*/, 
       
   593                                                   const TDesC&       /*aTo*/, 
       
   594                                                   const TDesC&       /*aSubject*/,
       
   595                                                   TInt64             aDate )
       
   596     {
       
   597     __LOG_ENTER("DoMessageUpdateL")
       
   598     
       
   599     if ( iIsAutoRefresh && iFolderId == aFolderId )
       
   600         {
       
   601         if ( aOperation == EMsgStoreAdd )
       
   602             {
       
   603             //add the row
       
   604             TInt32 newValue = GetValueFromSortingTableL( aMessageId );
       
   605             AddRowL( aMessageId, aDate, newValue );
       
   606             }
       
   607         else if ( aOperation == EMsgStoreDelete )
       
   608             {
       
   609             //delete the row
       
   610             DeleteRowL( aMessageId );
       
   611             }
       
   612         else if ( aOperation == EMsgStoreUpdateProperties )
       
   613             {
       
   614             //add the row
       
   615             TInt32 newValue = GetValueFromSortingTableL( aMessageId );
       
   616             UpdateRowL( aMessageId, aDate, newValue );
       
   617             }
       
   618         }
       
   619     
       
   620     __LOG_EXIT
       
   621     }
       
   622 
       
   623 // ==========================================================================
       
   624 // FUNCTION: FolderDeleted
       
   625 // ==========================================================================
       
   626 void CMsgStoreInMemorySortRowSet::FolderDeleted ( TContainerId aFolderId )
       
   627     {
       
   628     __LOG_ENTER("FolderDeleted")
       
   629     
       
   630     if ( iIsAutoRefresh && iFolderId == aFolderId )
       
   631         {
       
   632         //this folder does not exist anymore.
       
   633         //reset and re-evaluate the view
       
   634         TRAP_IGNORE( DeleteAllRowsL() );     
       
   635         }
       
   636     
       
   637     __LOG_EXIT
       
   638     }
       
   639 
       
   640 // ==========================================================================
       
   641 // FUNCTION: MailBoxDeleted
       
   642 // ==========================================================================
       
   643 void CMsgStoreInMemorySortRowSet::MailBoxDeleted ( TContainerId aMailBoxId )
       
   644     {
       
   645     __LOG_ENTER( "MailBoxDeleted" )
       
   646     
       
   647     if ( iIsAutoRefresh && iMailBoxId == aMailBoxId )
       
   648         {
       
   649         //this mail box has been deleted, so the folder does not exist anymore.
       
   650         //reset and re-evaluate the view
       
   651         TRAP_IGNORE( DeleteAllRowsL() );     
       
   652         }
       
   653     
       
   654     __LOG_EXIT
       
   655     }
       
   656 		
       
   657 // ==========================================================================
       
   658 // FUNCTION: DeleteAllRowsL
       
   659 // ==========================================================================
       
   660 void CMsgStoreInMemorySortRowSet::DeleteAllRowsL()
       
   661     {
       
   662     InitState();
       
   663     ResetAndEvaluateViewL();
       
   664     }
       
   665 
       
   666 // ==========================================================================
       
   667 // FUNCTION: AddRowL
       
   668 // ==========================================================================
       
   669 void CMsgStoreInMemorySortRowSet::AddRowL( TContainerId aMessageId, TInt64 aDate, TInt32 aValue )
       
   670     {
       
   671     CIntegerRow* row = new(ELeave) CIntegerRow( aMessageId, aDate, aValue );    
       
   672     InsertInOrderL( row );
       
   673     
       
   674     TInt64 groupValue = GetGroupValue( *row );
       
   675     UpdateGroupListL( groupValue );
       
   676     }
       
   677 
       
   678 // ==========================================================================
       
   679 // FUNCTION: DeleteRowL
       
   680 // ==========================================================================
       
   681 void CMsgStoreInMemorySortRowSet::DeleteRowL( TContainerId aMessageId )
       
   682     {
       
   683     __LOG_ENTER("DeleteRowL")
       
   684     
       
   685     CIntegerRow* tmpRow = new(ELeave) CIntegerRow( aMessageId, 0, 0 );
       
   686     CleanupStack::PushL( tmpRow );
       
   687     
       
   688     TInt index = iSortedIdArray.FindInOrder( tmpRow, &CIntegerRow::MessageIdAsc );
       
   689     if ( index >= 0 )
       
   690         {
       
   691         CIntegerRow *row = iSortedIdArray[index];
       
   692         CleanupStack::PushL( row );
       
   693         
       
   694         iSortedIdArray.Remove( index );
       
   695         
       
   696         index = iSortedResultArray.FindInOrder( row, iSortMethod );
       
   697         if ( index >= 0 )
       
   698             {
       
   699             iSortedResultArray.Remove( index );
       
   700             }
       
   701 
       
   702         //update the group name array
       
   703         TInt64 groupValue = GetGroupValue( *row );
       
   704         CIntegerSortGroup *gn = new(ELeave)CIntegerSortGroup( groupValue );
       
   705         CleanupStack::PushL( gn );
       
   706         
       
   707         TInt index = KErrNotFound;
       
   708         if ( iSortCriteria.iSortOrder == EMsgStoreSortDescending )
       
   709             {
       
   710             index = iGroupNameArray.FindInOrder( gn, CIntegerSortGroup::ValueDesc );
       
   711             }
       
   712         else
       
   713             {
       
   714             index = iGroupNameArray.FindInOrder( gn, CIntegerSortGroup::ValueAsc );
       
   715             }
       
   716             
       
   717         if ( index >= 0 )
       
   718             {
       
   719             CIntegerSortGroup* cur = iGroupNameArray[index];
       
   720             if ( cur->Count() <= 1 )
       
   721                 {
       
   722                 iGroupNameArray.Remove( index );
       
   723                 delete cur;
       
   724                 }
       
   725             else
       
   726                 {
       
   727                 cur->DecrementCount();
       
   728                 }            
       
   729             CleanupStack::Pop( gn );
       
   730             }
       
   731         else
       
   732         	{
       
   733             CleanupStack::PopAndDestroy( gn );
       
   734         	}
       
   735             
       
   736         CleanupStack::PopAndDestroy( row );
       
   737         }
       
   738     
       
   739     CleanupStack::PopAndDestroy( tmpRow );
       
   740     
       
   741     //DO NOT Re-evaluate
       
   742     __LOG_EXIT
       
   743     }
       
   744 
       
   745 // ==========================================================================
       
   746 // FUNCTION: UpdateRowL
       
   747 // ==========================================================================
       
   748 void CMsgStoreInMemorySortRowSet::UpdateRowL( TContainerId aMessageId, TInt64 aDate, TInt32 aValue )
       
   749     {
       
   750     __LOG_ENTER("UpdateRowL")
       
   751     
       
   752     DeleteRowL( aMessageId );
       
   753     AddRowL( aMessageId, aDate, aValue );
       
   754     
       
   755     __LOG_EXIT
       
   756     }
       
   757 
       
   758 // ==========================================================================
       
   759 // FUNCTION: InitState
       
   760 // ==========================================================================
       
   761 void CMsgStoreInMemorySortRowSet::InitState()
       
   762     {
       
   763     iCursorInWindow = -1;
       
   764     iSortedResultArray.Reset();
       
   765     iSortedIdArray.ResetAndDestroy();
       
   766     }
       
   767 
       
   768 // ==========================================================================
       
   769 // FUNCTION: InsertInOrderL
       
   770 // ==========================================================================
       
   771 void CMsgStoreInMemorySortRowSet::InsertInOrderL( CIntegerRow* aRow )
       
   772     {
       
   773     __LOG_ENTER_SUPPRESS( "InsertInOrderL" )
       
   774     CleanupStack::PushL( aRow );
       
   775     
       
   776     //add it to the iSortedResultArray first
       
   777     TInt rc = iSortedResultArray.InsertInOrderAllowRepeats( aRow, iSortMethod );
       
   778     if ( rc < 0 )
       
   779         {
       
   780         __LOG_WRITE_FORMAT1_ERROR( "Insert to Results array failed. err=%d", rc )
       
   781         User::Leave( rc );
       
   782         }
       
   783     
       
   784     //now add it to the id array and check the result
       
   785     rc = iSortedIdArray.InsertInOrder( aRow, &CIntegerRow::MessageIdAsc );
       
   786     if ( rc != KErrNone )
       
   787         {
       
   788         //fialed to add to the id array, remove it from the result array and leave
       
   789         __LOG_WRITE_FORMAT1_ERROR( "Insert to ID array failed. err=%d", rc )
       
   790         
       
   791         TInt ndx = iSortedResultArray.FindInOrder( aRow, iSortMethod );
       
   792         iSortedResultArray.Remove( ndx );
       
   793         User::Leave( KErrCorrupt );
       
   794         }
       
   795     
       
   796     CleanupStack::Pop( aRow );
       
   797     }
       
   798 
       
   799 // ==========================================================================
       
   800 // FUNCTION: ResetAndEvaluateViewL
       
   801 // ==========================================================================
       
   802 void CMsgStoreInMemorySortRowSet::ResetAndEvaluateViewL()
       
   803     {
       
   804     __LOG_ENTER( "ResetAndEvaluateViewL" )
       
   805     
       
   806     iDbView.Reset();
       
   807     User::LeaveIfError( iDbView.EvaluateAll() );
       
   808     
       
   809     __LOG_EXIT
       
   810     }
       
   811 
       
   812 // ==========================================================================
       
   813 // FUNCTION: GetGroupValue
       
   814 // ==========================================================================
       
   815 TInt64 CMsgStoreInMemorySortRowSet::GetGroupValue( CIntegerRow& aRow )
       
   816 	{
       
   817 	TInt64 value;
       
   818 	if ( iSortCriteria.iSortBy == EMsgStoreSortByReceivedDate )
       
   819 		{
       
   820 		value = aRow.ReceivedTime();
       
   821 		}
       
   822 	else
       
   823 		{
       
   824 		value = aRow.Value();
       
   825 		}
       
   826 	return value;
       
   827 	}
       
   828 
       
   829 // ==========================================================================
       
   830 // FUNCTION: GetGroupValue
       
   831 // ==========================================================================
       
   832 TInt32 CMsgStoreInMemorySortRowSet::GetValueFromSortingTableL( TContainerId aMessageId )
       
   833 	{
       
   834 	TInt32 newValue = iSortingTable.GetIntValueL( iSortCriteria.iSortBy, aMessageId );
       
   835 	return newValue;
       
   836 	}
       
   837 
       
   838 void CMsgStoreInMemorySortRowSet::GetDateRangeL( CIntegerRow& aRow, TMsgStoreIteratorDirection /*aDirection*/, TInt64& aDateStart, TInt64& aDateEnd )
       
   839 	{
       
   840 	TTime dayBoundary;
       
   841 	GetStartOfLocalDayL( aRow.ReceivedTime(), dayBoundary );
       
   842 	
       
   843     //We are search from earlier date to find the next date if 
       
   844     //    1) sort order is ASCENDING and movinf FORWARD, or
       
   845     //    2) sort order is DESCENDING and moving BACKWARD
       
   846     //We are search from later date to find the previous date if
       
   847     //    1) sort order is DESCENDING and moving FORWARD, or
       
   848     //    2) sort order is ASCENDING and moving BACKWARD
       
   849 //    if ( ( iSortOrder == EMsgStoreSortAscending && aDirection == EMsgStoreIteratorForward ) ||
       
   850 //         ( iSortOrder == EMsgStoreSortDescending && aDirection == EMsgStoreIteratorBackward ) )
       
   851 //        {
       
   852         aDateStart = dayBoundary.Int64();
       
   853         TTimeIntervalDays day(1);
       
   854         dayBoundary += day;
       
   855         aDateEnd = dayBoundary.Int64();
       
   856 //        }
       
   857 //    else
       
   858 //        {
       
   859 //        aDateEnd = dayBoundary.Int64();
       
   860 //        TTimeIntervalDays aDay(1);
       
   861 //        dayBoundary -= aDay;
       
   862 //        aDateStart = dayBoundary.Int64();
       
   863 //        }
       
   864 	}
       
   865 
       
   866 void CMsgStoreInMemorySortRowSet::GetStartOfLocalDayL( TInt64 aTime, TTime& aDayBoundary )
       
   867 	{
       
   868 	__LOG_ENTER_SUPPRESS( "GetStartOfLocalDayL" )
       
   869 	
       
   870 	TTime curTime( aTime );
       
   871 	
       
   872 #ifdef _DEBUG
       
   873 	const TUint bufSize =100;   
       
   874     TBuf<bufSize> timeString;
       
   875     _LIT( KDateTimeFormat, "%F%M/%D/%Y %H:%T:%S" );
       
   876     curTime.FormatL( timeString, KDateTimeFormat() );
       
   877     __LOG_WRITE_FORMAT1_INFO( "cur msg time=%S", &timeString )
       
   878     
       
   879 #endif
       
   880     
       
   881     //get the local time
       
   882     curTime += iUtcOffsetInSeconds;
       
   883     //change it to 0 o'clock
       
   884     TDateTime curDT = curTime.DateTime();
       
   885     TDateTime dayBoundary( curDT.Year(), curDT.Month(), curDT.Day(), 0, 0, 0, 0 );
       
   886     TTime timeBoundary( dayBoundary );
       
   887     //change it back to UTC
       
   888     timeBoundary -= iUtcOffsetInSeconds;
       
   889     
       
   890 #ifdef _DEBUG
       
   891     timeBoundary.FormatL( timeString, KDateTimeFormat() );
       
   892     __LOG_WRITE_FORMAT1_INFO( "timeBoundary=%S", &timeString )
       
   893     
       
   894 #endif
       
   895     
       
   896     aDayBoundary = timeBoundary;
       
   897 	}
       
   898