uiservicetab/vimpststorage/src/cvimpststoragecontactlist.cpp
changeset 0 5e5d6b214f4f
child 14 9fdee5e1da30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiservicetab/vimpststorage/src/cvimpststoragecontactlist.cpp	Tue Feb 02 10:12:18 2010 +0200
@@ -0,0 +1,600 @@
+/*
+* Copyright (c) 2008 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:  Contact list container implementation
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "cvimpststoragecontactlist.h"
+#include "vimpststorageutils.h"
+#include "cvimpststoragecontactsorter.h"
+#include "mvimpststoragecontact.h"
+#include "mvimpststoragecontactsobserver.h"
+#include "tvimpststoragepanics.h"
+#include "vimpstdebugtrace.h"
+#include "vimpstdebugassert.h"
+#include "cvimpststoragecontact.h"
+
+#include <MVPbkContactLink.h> //vpbk
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// Compares two contacts
+TInt CompareUserIdAlphabetically(
+                           const MVIMPSTStorageContact& aFirst,
+                           const MVIMPSTStorageContact& aSecond )
+    {
+    return VIMPSTStorageUtils::NeutralCompare( aFirst.UserId(), aSecond.UserId() );
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::CVIMPSTStorageContactList
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CVIMPSTStorageContactList::CVIMPSTStorageContactList( CVIMPSTStorageContactSorter& aSorter ) 
+: iSorter( aSorter )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CVIMPSTStorageContactList::ConstructL( const TDesC& aContactListId, 
+                                 const TDesC& aDisplayName )
+    {
+    iListId = aContactListId.AllocL();  
+    iDisplayName = aDisplayName.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CVIMPSTStorageContactList* CVIMPSTStorageContactList::NewL(CVIMPSTStorageContactSorter& aSorter,
+					                                      const TDesC& aContactListId, 
+					                                      const TDesC& aDisplayName )
+    {
+    CVIMPSTStorageContactList* self = NewLC(  aSorter,
+			                                  aContactListId, 
+			                                  aDisplayName );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CVIMPSTStorageContactList* CVIMPSTStorageContactList::NewLC(CVIMPSTStorageContactSorter& aSorter,
+					                                       const TDesC& aContactListId, 
+					                                       const TDesC& aDisplayName )
+    {
+    CVIMPSTStorageContactList* self = new( ELeave ) CVIMPSTStorageContactList(aSorter );
+    CleanupStack::PushL( self );
+    self->ConstructL( aContactListId, aDisplayName );
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::destructor
+// -----------------------------------------------------------------------------
+//
+CVIMPSTStorageContactList::~CVIMPSTStorageContactList()
+    {
+    iContactArray.ResetAndDestroy();
+    iContactArray.Close();
+    iOrderedContacts.Reset();
+    delete iListId;
+    delete iDisplayName;
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::ListId
+// -----------------------------------------------------------------------------
+//
+const TDesC& CVIMPSTStorageContactList::ListId() const
+    {
+    if( iListId )
+        {
+        return *iListId;
+        }
+    return KNullDesC;        
+    }
+    
+       
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::DisplayName
+// -----------------------------------------------------------------------------
+//
+TPtrC CVIMPSTStorageContactList::DisplayName() const
+    {
+    if( iDisplayName )
+        {
+        return *iDisplayName;
+        }
+    return KNullDesC();
+    }
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::AddStorageContactToCacheL
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::AddStorageContactToCacheL( MVIMPSTStorageContact* aContact, TInt& aIndex )
+    {
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL begin") ); 
+    
+    if( !aContact )
+	    {
+	    return KErrArgument;	
+	    }
+    TPtrC userID = aContact->UserId();
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL userId = %S"), &userID ); 
+    // optimize insert for inserting of reverse alphabetical order
+    TInt idIndex( 0 );
+    TInt count( iOrderedContacts.Count() );
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL count = %d"),count ); 
+    if( count && aContact->UserId().Length() &&
+    	 ( 0 <= VIMPSTStorageUtils::NeutralCompare( aContact->UserId(),
+    								  iOrderedContacts[ 0 ]->UserId() ) ) )
+    	{
+    	TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL inside if") ); 
+    	// there are items and the contact should not be inserted to beginning
+    	// => find the correct place
+	    TLinearOrder< MVIMPSTStorageContact > userIdOrder( *CompareUserIdAlphabetically );
+	    if( KErrNone == iOrderedContacts.FindInOrder( aContact, idIndex, userIdOrder ) )
+    	    {
+    	    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL contact already exists.") ); 
+            // this contact already exists, return it
+            return KErrAlreadyExists;
+            }
+    	}
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL inserting the contact") ); 
+    // the position is now correct, insert the contact
+    iOrderedContacts.InsertL( aContact, idIndex );
+
+    // insert also to list sorted by contact "identification"
+    TInt err( KErrNone );
+    count = iContactArray.Count();  
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL iContactsArray count %d"),count ); 
+    TLinearOrder< MVIMPSTStorageContact >& order = iSorter.InsertOrder();
+    if( count &&  0 > (*order)( aContact, iContactArray[ 0 ] ) )
+    	{
+    	// the item should be inserted in the beginning of the array
+		err = iContactArray.Insert( aContact, 0 );
+    	}
+    else
+       	{
+       	// insert in correct position
+       	err = iContactArray.InsertInOrderAllowRepeats( aContact, order );
+       	}
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL iContactsArray inserting error %d"),err ); 
+    if( err != KErrNone )
+        {
+        // appending to second array did not succeed, so remove from first and leave
+        iOrderedContacts.Remove( idIndex );
+        User::Leave( err );
+        }
+    aIndex = idIndex;
+    TRACE( T_LIT("CVIMPSTStorageContactList::AddStorageContactToCacheL End") ); 
+    return err;
+    }
+ 
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::RemoveContactFromCacheL
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::RemoveContactFromCacheL( const TDesC& aContactId, TInt& aIndex )
+    {
+    TInt orderedIndex(0);
+    TInt contactIndex = FindContactIndex( aContactId, orderedIndex );
+	aIndex = contactIndex;
+    if( KErrNotFound != contactIndex )
+        {
+        delete iContactArray[ contactIndex ];
+        iContactArray.Remove( contactIndex );
+        iOrderedContacts.Remove( orderedIndex );
+        iContactArray.Compress();
+        iOrderedContacts.Compress();
+        return KErrNone;
+        }
+    return KErrNotFound;
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::RemoveContactFromCacheL
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::RemoveContactFromCacheL( const MVPbkContactLink& aContactLink, TInt& index )
+    {
+    TInt error = KErrNotFound;
+    TInt orderedIndex(0);
+    TInt contactIndex = FindContactByLinkL( aContactLink, orderedIndex );
+	index = contactIndex;
+    if( KErrNotFound != contactIndex )
+        {
+        MVIMPSTStorageContact* contact = iContactArray[ contactIndex ];
+        iContactArray.Remove( contactIndex );
+        iOrderedContacts.Remove( orderedIndex );
+        delete contact;
+        iContactArray.Compress();
+        iOrderedContacts.Compress();
+        error = KErrNone;
+        }
+    return error;
+    }    
+ // -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindContact
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::ContactCount( TBool aSkipOfflineContacts,
+						   TBool aSkipBlocekedContacts ) const
+    {
+    if( !aSkipOfflineContacts && !aSkipBlocekedContacts )
+        {
+        return iContactArray.Count();
+        }
+    TInt countOfContacts( 0 );
+    TInt count( iContactArray.Count() );
+    for( TInt a( 0 ); a < count; ++a )
+        {
+        TVIMPSTEnums::TOnlineStatus status(
+                                    iContactArray[ a ]->OnlineStatus() );
+        if( status == TVIMPSTEnums::EOnline ||
+            status == TVIMPSTEnums::EAway ||
+            status == TVIMPSTEnums::EBusy ||
+            status == TVIMPSTEnums::EDoNotDisturb )
+            {
+	        ++countOfContacts;
+            }
+        }
+    return countOfContacts;
+    }
+            
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindContactIndex
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::FindContactIndex( const TDesC& aUserId,
+                                       TInt& aOrderedIndex ) const
+    {
+     TInt low( 0 );
+    TInt high( iOrderedContacts.Count() );
+    while( high > low )
+        {
+        TInt m( ( low + high ) / 2 );
+        TInt compare( VIMPSTStorageUtils::NeutralCompare( aUserId, iOrderedContacts[ m ]->UserId() ) );
+        if ( compare == KErrNone )
+            {
+            aOrderedIndex = m;
+            return FindContactEntry( iOrderedContacts[ m ] );
+            }
+        else if ( compare > 0 )
+            {
+            low = m + 1;
+            }
+        else
+            {
+            high = m;
+            }
+        }
+    aOrderedIndex = KErrNotFound;
+    return KErrNotFound;
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindContactEntry
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::FindContactEntry( const MVIMPSTStorageContact* aContact ) const
+    {
+    TInt index( iContactArray.Find( aContact ) );
+    __ASSERT_DEBUG( index != KErrNotFound , Panic( EContactsArrayOutOfSync ));
+    return index;
+    }
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::Sort
+// -----------------------------------------------------------------------------
+//
+void CVIMPSTStorageContactList::Sort()
+    {
+    iSorter.Sort( iContactArray );
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::ResortContact
+// -----------------------------------------------------------------------------
+//
+void CVIMPSTStorageContactList::ResortContact( MVIMPSTStorageContact* aContact )
+    {
+    // let it panic, if index is not found, which would be bad
+    TInt index( iContactArray.Find( aContact ) );
+    __ASSERT_DEBUG( index != KErrNotFound , Panic( ESortingCorupted ));
+    // Check if resort is even needed for the contact
+    TLinearOrder< MVIMPSTStorageContact >& order = iSorter.InsertOrder();
+    if(
+        (
+          ( index == 0 )
+          ||
+          ( 0 >= (*order)( iContactArray[ index - 1], aContact ) )
+        )
+        &&
+        (
+          ( index == ( iContactArray.Count() - 1 ) )
+          ||
+          ( 0 <= (*order)( iContactArray[ index + 1], aContact ) )
+        )
+      )
+        {
+        // the item is in correct position
+        // => no need to resort
+        return;
+        }
+    
+    iContactArray.Remove( index );
+    // this should alway succeed, since we did not actually add anything to array
+    // no need to add contact to the ordered array, should be there already
+    TInt err( iContactArray.InsertInOrderAllowRepeats( aContact, order ) );
+    __ASSERT_DEBUG( err == KErrNone , Panic( ESortingCorupted ));
+    }
+   
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindIndexOfContact
+// From MVIMPSTContactList
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::FindIndexOfContact( const MVIMPSTStorageContact* aContact,
+                            TVIMPSTEnums::TFilterType aFilter  ) const
+    {    
+    TInt count( iContactArray.Count() ); 
+    if ( aFilter == TVIMPSTEnums::EFilterAll )
+		{
+        for( TInt a( 0 ); a < count; ++a )
+            {
+            const MVIMPSTStorageContact* contact = iContactArray[ a ];
+            if( aContact == contact )
+                {
+                return a;
+                }
+            }		
+		}
+	else
+	    {
+	    TInt filteredIndex( -1 );
+	    for( TInt i( 0 ); i < count; ++i )
+            {
+            MVIMPSTStorageContact* contact ( iContactArray[i] );
+            if ( FilterAllowsContact( contact, aFilter ) )
+                {
+                // contact was in the correct state
+                filteredIndex++; 
+                if( contact == aContact)
+                    {
+                    // Contact was found, return the index
+                    return filteredIndex;
+                    }                  
+                }        
+            }    
+	    }
+    return KErrNotFound;
+    }
+       
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::Count
+// From MVIMPSTStorageContactList
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::Count() const
+    {
+    return ContactCount( EFalse, EFalse );
+    }
+    
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::OnlineCount
+// From MVIMPSTStorageContactList
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::OnlineCount() const
+    {
+    return FilteredCount( TVIMPSTEnums::EFilterNonOffline );
+    }
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::operator[]
+// From MVIMPSTStorageContactList
+// -----------------------------------------------------------------------------
+//
+MVIMPSTStorageContact& CVIMPSTStorageContactList::operator[]( TInt aIndex ) const
+    {
+    __CHAT_ASSERT_DEBUG( aIndex < iContactArray.Count() )
+    return *iContactArray[ aIndex ];
+    }
+    
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::OnlineContact
+// From MVIMPSTContactList
+// -----------------------------------------------------------------------------
+//
+MVIMPSTStorageContact& CVIMPSTStorageContactList::OnlineContact( TInt aIndex ) const
+    {
+    return FilteredContact( 
+                aIndex, TVIMPSTEnums::EFilterNonOffline );
+    }
+ 
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FilteredContact
+// From MVIMPSTContactList
+// -----------------------------------------------------------------------------
+//
+MVIMPSTStorageContact& CVIMPSTStorageContactList::FilteredContact( 
+                TInt aIndex, TVIMPSTEnums::TFilterType aFilter ) const
+	{
+    if ( aFilter == TVIMPSTEnums::EFilterAll )
+		{
+		return (*this)[aIndex];
+		}
+	else
+        {      
+        TInt filteredIndex( -1 );
+        TInt count( iContactArray.Count() );
+        for( TInt i(0); i < count; ++i )
+            {
+            MVIMPSTStorageContact* contact = iContactArray[i];
+            if ( FilterAllowsContact( contact, aFilter ) )
+                {
+                // Contact was in correct state
+                filteredIndex++;
+                if ( aIndex == filteredIndex )
+                    {
+                    // index was also correct
+                    return *iContactArray[i];                   
+                    } 
+                }
+            }
+	    __CHAT_ASSERT_DEBUG( EFalse );
+        // prevent compiler warning
+        return ( MVIMPSTStorageContact& )KNullDesC;
+        }
+	}
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FilteredCount
+// From MVIMPSTContactList
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::FilteredCount( 
+                            TVIMPSTEnums::TFilterType aFilter ) const
+	{
+    if ( aFilter == TVIMPSTEnums::EFilterAll )
+		{
+		return Count();
+		}
+	TInt filtered( 0 );
+	TInt count( iContactArray.Count() );
+	for( TInt i( 0 ); i<count; ++i )
+		{
+		if ( FilterAllowsContact( iContactArray[i], aFilter ) )
+			{
+			filtered++;                
+			}
+		}
+	return filtered;
+  	}
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FilterAllowsContact
+// -----------------------------------------------------------------------------
+//
+TBool CVIMPSTStorageContactList::FilterAllowsContact( const MVIMPSTStorageContact* aContact,
+                             TVIMPSTEnums::TFilterType aFilter ) const
+    {
+    TBool showContact( EFalse );
+    TInt myStatus( KErrNone );          
+    TVIMPSTEnums::TOnlineStatus status(
+                            aContact->OnlineStatus() );                                          
+
+    if( aFilter & TVIMPSTEnums::EFilterAndOperation )
+        {                
+        myStatus = myStatus | TVIMPSTEnums::EFilterAndOperation;
+        }
+     
+    if ( status == TVIMPSTEnums::EOnline )
+        {
+        myStatus = myStatus | TVIMPSTEnums::EFilterOnline;
+        }
+
+    if ( status == TVIMPSTEnums::EOnline || 
+         status == TVIMPSTEnums::EAway ||
+         status == TVIMPSTEnums::EBusy ||
+         status == TVIMPSTEnums::EDoNotDisturb)
+        {
+        myStatus = myStatus | TVIMPSTEnums::EFilterNonOffline;
+        }
+
+    if ( status == TVIMPSTEnums::EAway)
+        {
+        myStatus |= TVIMPSTEnums::EFilterAway;
+        }
+    
+    if( aFilter & TVIMPSTEnums::EFilterAndOperation )
+        {
+        if( ( myStatus & aFilter ) == aFilter )
+            {
+            showContact = ETrue;
+            }
+        }
+    else
+        {
+        if( myStatus & aFilter )
+            {
+            showContact = ETrue;
+            }
+        } 
+       
+    return showContact;   
+    }
+
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindContact
+// -----------------------------------------------------------------------------
+//
+MVIMPSTStorageContact* CVIMPSTStorageContactList::FindContact( const TDesC& aContactId )
+    {
+    TInt orderedIndex(0);
+    TInt contactIndex = FindContactIndex( aContactId, orderedIndex );
+    return ( contactIndex >= 0 ? iContactArray[ contactIndex ] : NULL );
+    }
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindContactByContactLinkL
+// -----------------------------------------------------------------------------
+//
+MVIMPSTStorageContact* CVIMPSTStorageContactList::FindContactByContactLink( const MVPbkContactLink& aContactLink )
+    {
+    TInt orderedIndex(0);
+    TInt contactIndex = -1;
+    TRAP_IGNORE( contactIndex = FindContactByLinkL( aContactLink, orderedIndex );)
+    return ( contactIndex >= 0 ? iContactArray[ contactIndex ] : NULL );
+    }
+    
+// -----------------------------------------------------------------------------
+// CVIMPSTStorageContactList::FindContactByLinkL
+// -----------------------------------------------------------------------------
+//
+TInt CVIMPSTStorageContactList::FindContactByLinkL( const MVPbkContactLink& aContactLink,
+                                          TInt& aIndexOrderedArray ) const
+    {
+    TInt count( iOrderedContacts.Count() );
+    TInt contactIndex = KErrNotFound;
+     //Does a Linear Search
+    for (TInt index = 0; index<count; index++)
+		{
+		MVPbkContactLink* contactLink = iOrderedContacts[ index ]->ContactLink();
+		if( contactLink && contactLink->IsSame( aContactLink ) )
+			{
+			aIndexOrderedArray = index;
+		    contactIndex =  FindContactEntry( iOrderedContacts[ index ] );
+		    break;	
+			}
+		} 
+    return contactIndex;
+    }        
+    
+//  End of File