ipsservices/ipssosplugin/src/ipsplgmsgkey.cpp
changeset 0 8466d47a6819
child 20 efd4f1afd43e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ipsservices/ipssosplugin/src/ipsplgmsgkey.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,329 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Key class for message sorting
+*
+*/
+
+// <cmail>
+#include <AknUtils.h>
+// </cmail>
+
+#include "emailtrace.h"
+#include "ipsplgheaders.h"
+
+const TInt KLessThan = -1;
+const TInt KMoreThan = 1;
+const TInt KEqual = 0;
+
+_LIT(KDefaultSubjectPrefixSeparator,": ");
+// <cmail>
+_LIT( KCharsToReplace, "\r\n\t\x2028\x2029" );
+// </cmail>
+
+// ---------------------------------------------------------------------------
+// Basic sonstructor
+// ---------------------------------------------------------------------------
+
+TIpsPlgMsgKey::TIpsPlgMsgKey( 
+    CMsvEntry& aFolderEntry,
+    const RArray<TFSMailSortCriteria>& aSortCriteria )
+    : iFolderEntry( aFolderEntry ), 
+      iSortingCriteria( aSortCriteria ),
+      iSubjectPrefixSeparator( KDefaultSubjectPrefixSeparator )
+    {
+    FUNC_LOG;
+    // none
+    }
+
+// ---------------------------------------------------------------------------
+// Compares the messages under the folder entry according to the sorting
+// criteria.
+// ---------------------------------------------------------------------------
+
+TInt TIpsPlgMsgKey::Compare( TInt aLeft, TInt aRight ) const
+    {
+    FUNC_LOG;
+    TInt result( KEqual );
+    TInt childCount( iFolderEntry.Count() );
+    if ( aLeft >= childCount || aRight >= childCount  )
+        {
+        return result;
+        }
+    const TMsvEmailEntry leftEntry( iFolderEntry[aLeft] );
+    const TMsvEmailEntry rightEntry( iFolderEntry[aRight] );
+    
+    // Loop over the sorting criteria until the comparison result is known
+    TInt i(0);
+    while ( ( result == KEqual ) && ( i < iSortingCriteria.Count() ) )
+        {
+        switch ( iSortingCriteria[i].iField )
+            {
+            case EFSMailDontCare:
+                {
+                // If the client does not care, we can return immediately
+                return result;
+                }
+            case EFSMailSortByDate:
+                {
+                if ( leftEntry.iDate < rightEntry.iDate ) 
+                    {
+                    result = KLessThan;
+                    }
+                else if ( leftEntry.iDate > rightEntry.iDate ) 
+                    {
+                    result = KMoreThan;
+                    }
+                break;
+                }
+            case EFSMailSortBySender:
+                {
+                result = 
+                    leftEntry.iDetails.CompareC( rightEntry.iDetails );
+                break;
+                }
+            case EFSMailSortByRecipient:
+                {                
+                result = 
+                    leftEntry.iDetails.CompareC( rightEntry.iDetails );
+                break;
+                }
+            case EFSMailSortBySubject:
+                {
+                // <cmail> due to changes in CompareSubject method
+                TRAP_IGNORE( result = CompareSubjectsL( 
+                    leftEntry.iDescription, rightEntry.iDescription ) );
+                // </cmail>
+                break;
+                }
+            case EFSMailSortByPriority:
+                // The values of TMsvPriority are defined so that the highest
+                // priority has the smallest value
+                if ( leftEntry.Priority() > rightEntry.Priority() ) 
+                    {
+                    result = KLessThan;
+                    }
+                else if ( leftEntry.Priority() < rightEntry.Priority() ) 
+                    {
+                    result = KMoreThan;
+                    }
+                break;
+            case EFSMailSortByFlagStatus:
+                {
+                // The 'flagged' state is supported only in IMAP4
+                if ( leftEntry.iMtm == KUidMsgTypeIMAP4 )
+                    {
+                    if ( !leftEntry.FlaggedIMAP4Flag() && 
+                         rightEntry.FlaggedIMAP4Flag() ) 
+                        {
+                        result = KLessThan;
+                        }
+                    else if ( leftEntry.FlaggedIMAP4Flag() && 
+                              !rightEntry.FlaggedIMAP4Flag() ) 
+                        {
+                        result = KMoreThan;
+                        }
+                    }
+                break;
+                }
+            case EFSMailSortByUnread:
+                {
+                // In this context, an read message is 'greater' than
+                // a read one
+                if ( !leftEntry.Unread() && rightEntry.Unread() ) 
+                    {
+                    result = KMoreThan; // <cmail> changed from KLessThan 
+                    }
+                else if ( leftEntry.Unread() && !rightEntry.Unread() ) 
+                    {
+                    result = KLessThan; // <cmail> changed from KMoreThan
+                    }
+                break;
+                }
+            case EFSMailSortBySize:
+                {
+                if ( leftEntry.iSize < rightEntry.iSize ) 
+                    {
+                    result = KLessThan;
+                    }
+                else if ( leftEntry.iSize > rightEntry.iSize ) 
+                    {
+                    result = KMoreThan;
+                    }
+                break;
+                }
+            case EFSMailSortByAttachment:
+                {
+                // In this context, a message with an attachment is 'greater'
+                // than one without an attachment
+                if ( !leftEntry.Attachment() && rightEntry.Attachment() ) 
+                    {
+                    result = KLessThan;
+                    }
+                else if ( leftEntry.Attachment() && !rightEntry.Attachment() ) 
+                    {
+                    result = KMoreThan;
+                    }
+                break;
+                }
+            default:
+                break;
+            }
+            
+        // Switch the order if the messages are sorted in the descending order
+        if ( iSortingCriteria[i].iOrder == EFSMailDescending ) 
+            {
+            result = -result;
+            }
+        
+        i++;
+        }
+    
+    return result;
+    }
+
+// ---------------------------------------------------------------------------
+// Returns a message based on the index.
+// Note, that KIndexPtr index value is not supported as the class is not 
+// intended to be used with User::BinarySearch().
+// ---------------------------------------------------------------------------
+
+TAny* TIpsPlgMsgKey::At( TInt anIndex ) const
+    {
+    FUNC_LOG;
+    return (TAny*) &iFolderEntry[ anIndex ];
+    }
+
+// ---------------------------------------------------------------------------
+// Strips the subject prefixes before comparing the strings
+// ---------------------------------------------------------------------------
+
+TInt TIpsPlgMsgKey::CompareSubjectsL( 
+    const TDesC& aLeft, 
+    const TDesC& aRight ) const
+    {
+    FUNC_LOG;
+    TInt  result( KEqual );
+    TPtrC leftPtr( aLeft );
+    TPtrC rightPtr( aRight );
+    TInt  leftOffset( FindSubjectStart( aLeft ) );
+    TInt  rightOffset( FindSubjectStart( aRight ) );
+    
+    leftPtr.Set( 
+        leftPtr.Ptr() + leftOffset, leftPtr.Length() - leftOffset );
+    rightPtr.Set( 
+        rightPtr.Ptr() + rightOffset, rightPtr.Length() - rightOffset );
+    
+    // <cmail> for unifying with UI - remove all white spaces
+    HBufC* croppedLeft = leftPtr.AllocLC();
+    TPtr croppedLeftPtr = croppedLeft->Des();
+    HBufC* croppedRight = rightPtr.AllocLC();
+    TPtr croppedRightPtr = croppedRight->Des();
+        
+    AknTextUtils::ReplaceCharacters( croppedLeftPtr, KCharsToReplace, ' ' );
+    croppedLeftPtr.TrimAll();
+    AknTextUtils::ReplaceCharacters( croppedRightPtr, KCharsToReplace, ' ' );
+    croppedRightPtr.TrimAll();
+    
+    result = croppedLeftPtr.CompareC( croppedRightPtr );
+    
+    CleanupStack::PopAndDestroy( croppedRight );
+    CleanupStack::PopAndDestroy( croppedLeft );
+    // </cmail>
+        
+    return result;
+    }
+    
+// ---------------------------------------------------------------------------
+// Finds the starting point of the actual subject text after the subject
+// prefixes (Re:, Fwd: etc).
+// The algorithm search the last separator string (': ') in most western
+// languages and returns the offset from the beginnig of the string to
+// the first character following the last separator.
+// ---------------------------------------------------------------------------
+
+TInt TIpsPlgMsgKey::FindSubjectStart( const TDesC& aSubject ) const
+    {
+    FUNC_LOG;
+    TInt offset(0);
+    // <cmail> removed and replaced with the code from UI
+    // TFsEmailUiUtility::CreateSubjectWithoutLocalisedPrefixLC
+    // to have the same subject here and there
+    // there was sorting problem when subjects where handled
+    // different here and in UI while creating mails' list.  
+    
+    /*TPtrC ptr(aSubject);
+    TInt current(0);
+    TInt skipLength = iSubjectPrefixSeparator.Length();
+    
+    // Loop while separators are found
+    do
+        {
+        current = ptr.FindF( iSubjectPrefixSeparator );
+
+        if ( current != KErrNotFound )
+            {
+            offset += current + skipLength;
+            ptr.Set( aSubject.Ptr() + offset, aSubject.Length() - offset );
+            }
+        } while ( current != KErrNotFound );*/
+    
+    TBool prefixFound = EFalse;
+    TPtrC croppedSubject;
+    croppedSubject.Set( aSubject );
+    
+    do
+        {
+        prefixFound = EFalse;
+    
+        // Remove leading white space before trying to find the prefix
+        while( croppedSubject.Length() && 
+               TChar( croppedSubject[0] ).IsSpace() )
+            {
+            croppedSubject.Set( croppedSubject.Mid(1) );
+            offset++;
+            }
+    
+        // try to find ":" at the beginning
+        // Locate : character on location 1,2 and 3
+        static const TInt KPrefixMinLength = 1;
+        static const TInt KPrefixMaxLength = 3;
+        static const TText KPrefixSeparator = ':';
+        TInt separatorPosition = croppedSubject.Locate( KPrefixSeparator );
+        if ( separatorPosition >= KPrefixMinLength &&
+             separatorPosition <= KPrefixMaxLength )
+            {
+            TPtrC prefixCandidate = croppedSubject.Left( separatorPosition );
+            // Only fully alphabetic prefixes are cropped
+            TBool isAlpha = ETrue;
+            for ( TInt i = 0 ; i < prefixCandidate.Length() ; ++i )
+                {
+                if ( !TChar( prefixCandidate[i] ).IsAlpha() )
+                    {
+                    isAlpha = EFalse;
+                    }
+                }
+            if ( isAlpha )
+                {
+                croppedSubject.Set( croppedSubject.Mid( 
+                        separatorPosition + 1 ) );
+                offset += separatorPosition + 1;
+                prefixFound = ETrue;
+                }
+            }
+        }
+    while ( prefixFound );
+    // </cmail>
+
+    return offset;
+    }